mosquito-transport-js 0.4.3 → 0.4.7

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/TODO CHANGED
@@ -1,11 +1,11 @@
1
1
  - fix local cache query on sqlite ✅
2
- - fix and add all mongodb query and update operator
2
+ - fix and add all mongodb query and update operator
3
3
  - reauthenticate
4
4
  - change `Object` in d.ts to [key: string]: any
5
5
  - add `getServerTimeOffset` method
6
6
  - change undefined to null in `value` ✅
7
7
  - `provide functionality to add extra header to MT instance (all outgoing request)` ✅
8
- - borrowToken
8
+ - borrowToken
9
9
  - `add sqlite` ✅
10
10
  - minimize extraction data ✅
11
11
  - change `collection().onDisconnect()` to `collection().socket().onDisconnect()` and `collection().socket().onConnect()` ✅
@@ -14,10 +14,11 @@
14
14
  - dynamic import for fs ✅
15
15
  - new URL() work around ✅
16
16
  - fetchHttp, default retrieval if has body ✅
17
- - native hashing
17
+ - native hashing
18
18
  - TextEncoder
19
- - native storage upload
19
+ - native storage upload
20
20
  - lodashes ✅
21
21
  - switch to events package
22
22
  - serverTimeOffset
23
+ - avoid sending cookies ✅
23
24
  <!-- - error: "refreshToken retry limit exceeded" <--- no need -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mosquito-transport-js",
3
- "version": "0.4.3",
3
+ "version": "0.4.7",
4
4
  "description": "Javascript web sdk for mosquito-transport (https://github.com/brainbehindx/mosquito-transport)",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -28,15 +28,15 @@
28
28
  },
29
29
  "homepage": "https://github.com/brainbehindx/mosquito-transport-js#readme",
30
30
  "dependencies": {
31
- "@turf/turf": "^7.1.0",
31
+ "@turf/turf": "^7.2.0",
32
32
  "bson": "^6.8.0",
33
33
  "buffer": "^6.0.3",
34
- "entity-serializer": "^1.0.2",
35
- "guard-object": "^1.1.3",
34
+ "entity-serializer": "^1.0.3",
35
+ "guard-object": "^1.1.4",
36
36
  "limit-task": "1.0.0",
37
37
  "lodash": "^4.17.21",
38
38
  "simplify-error": "^1.0.1",
39
- "socket.io-client": "^4.6.2",
39
+ "socket.io-client": "^4.8.1",
40
40
  "subscription-listener": "^1.1.2",
41
41
  "tweetnacl-functional": "^1.0.5"
42
42
  },
@@ -11,6 +11,7 @@ export const listenReachableServer = (callback, projectUrl) => {
11
11
  let lastValue;
12
12
  return ServerReachableListener.listenTo(projectUrl, t => {
13
13
  if (typeof t === 'boolean' && t !== lastValue) callback?.(t);
14
+ lastValue = t;
14
15
  }, true);
15
16
  };
16
17
 
@@ -129,7 +129,8 @@ export const buildFetchInterface = async ({ body, authToken, method, uglify, ser
129
129
  'Content-type': uglify ? 'request/buffer' : 'application/json',
130
130
  ...(authToken && !uglify) ? { 'Mosquito-Token': authToken } : {}
131
131
  },
132
- method: method || 'POST'
132
+ method: method || 'POST',
133
+ credentials: 'omit'
133
134
  }, keyPair];
134
135
  };
135
136
 
package/src/index.d.ts CHANGED
@@ -71,6 +71,7 @@ export const AUTH_PROVIDER_ID: auth_provider_id;
71
71
  * useful for avoiding encrypting data and extra overhead
72
72
  */
73
73
  export class DoNotEncrypt {
74
+ constructor(value: any);
74
75
  value: any;
75
76
  }
76
77
 
@@ -419,7 +420,7 @@ interface DocumentWriteValue {
419
420
 
420
421
  interface MTAuth {
421
422
  customSignin: (email: string, password: string) => Promise<SigninResult>;
422
- customSignup: (email: string, password: string, name?: string, metadata?: Object) => Promise<SigninResult>;
423
+ customSignup: (email: string, password: string, name?: string, metadata?: Object) => Promise<SignupResult>;
423
424
  googleSignin: (token: string) => Promise<SignupResult>;
424
425
  appleSignin: () => Promise<SignupResult>;
425
426
  facebookSignin: () => Promise<SignupResult>;
@@ -525,7 +526,7 @@ interface DownloadProgressStats {
525
526
  }
526
527
 
527
528
  interface UploadProgressStats {
528
- sentBtyes: number;
529
+ sentBytes: number;
529
530
  totalBytes: number;
530
531
  }
531
532
 
package/src/index.js CHANGED
@@ -21,7 +21,8 @@ const {
21
21
  _listenDocument,
22
22
  _startDisconnectWriteTask,
23
23
  _cancelDisconnectWriteTask,
24
- _listenUserVerification
24
+ _listenUserVerification,
25
+ _areYouOk
25
26
  } = EngineApi;
26
27
 
27
28
  // https://socket.io/docs/v3/emit-cheatsheet/#reserved-events
@@ -73,12 +74,9 @@ export class MosquitoTransport {
73
74
  _from_base: true
74
75
  }
75
76
  });
76
-
77
- socket.on('_signal_signout', () => {
78
- this.auth().signOut();
79
- });
80
-
81
- socket.on('connect', () => {
77
+ let connectionIte = 0;
78
+ const onConnect = () => {
79
+ ++connectionIte;
82
80
  isConnected = true;
83
81
  Scoped.IS_CONNECTED[projectUrl] = true;
84
82
  if (queuedToken) updateMountedToken(queuedToken.token);
@@ -86,12 +84,33 @@ export class MosquitoTransport {
86
84
  awaitStore().then(() => {
87
85
  trySendPendingWrite(projectUrl);
88
86
  });
89
- });
90
-
91
- socket.on('disconnect', () => {
87
+ };
88
+ const onDisconnect = () => {
89
+ ++connectionIte;
92
90
  isConnected = false;
93
91
  Scoped.IS_CONNECTED[projectUrl] = false;
94
92
  ServerReachableListener.dispatch(projectUrl, false);
93
+ }
94
+
95
+ const manualCheckConnection = () => {
96
+ const ref = ++connectionIte;
97
+ fetch(_areYouOk(projectUrl), { cache: 'no-cache', credentials: 'omit' }).then(async r => {
98
+ if ((await r.json()).status === 'yes') {
99
+ if (ref === connectionIte) onConnect();
100
+ } else throw null;
101
+ }).catch(() => {
102
+ if (ref === connectionIte) onDisconnect();
103
+ });
104
+ }
105
+ manualCheckConnection();
106
+
107
+ socket.on('_signal_signout', () => {
108
+ this.auth().signOut();
109
+ });
110
+
111
+ socket.on('connect', onConnect);
112
+ socket.on('disconnect', () => {
113
+ manualCheckConnection();
95
114
  });
96
115
 
97
116
  const updateMountedToken = (token) => {
@@ -189,8 +208,11 @@ export class MosquitoTransport {
189
208
  socketListenerList = [],
190
209
  socketListenerIte = 0;
191
210
 
211
+ /**
212
+ * @type {import('socket.io-client').Socket}
213
+ */
214
+ let socket;
192
215
  let hasCancelled,
193
- socket,
194
216
  tokenListener,
195
217
  clientPrivateKey;
196
218
 
@@ -315,7 +337,7 @@ export class MosquitoTransport {
315
337
  lastTokenStatus = status || false;
316
338
  }, projectUrl);
317
339
  }
318
-
340
+ // TODO: disconnected
319
341
  return {
320
342
  timeout: (timeout) => {
321
343
  if (timeout !== undefined && !Validator.POSITIVE_INTEGER(timeout))
@@ -460,7 +482,7 @@ const ConfigValidator = {
460
482
  },
461
483
  extraHeaders: v => {
462
484
  if (!Validator.OBJECT(v)) throw '"extraHeaders" must be an object';
463
- const reservedHeaders = ['mtoken', 'mosquito-token', 'init-content-type', 'content-type', 'uglified'];
485
+ const reservedHeaders = ['mtoken', 'mosquito-token', 'init-content-type', 'content-type', 'uglified', 'entity-encoded'];
464
486
 
465
487
  Object.entries(v).forEach(([k, v]) => {
466
488
  if (typeof v !== 'string') throw `expected a string at extraHeaders.${k} but got "${v}"`;
@@ -220,7 +220,8 @@ const doCustomSignup = (builder, email, password, name, metadata) => new Promise
220
220
  resolve({
221
221
  user: parseToken(r.result.token),
222
222
  token: r.result.token,
223
- refreshToken: r.result.refreshToken
223
+ refreshToken: r.result.refreshToken,
224
+ isNewUser: !!r.result.isNewUser
224
225
  });
225
226
  await injectFreshToken(builder, r.result);
226
227
  revokeAuthIntance(builder, thisAuthStore);
@@ -285,7 +286,7 @@ export const purgePendingToken = async (nodeId) => {
285
286
  try {
286
287
  let isConnected;
287
288
  try {
288
- isConnected = (await (await fetch(_areYouOk(projectUrl))).json(), { cache: 'no-cache' }).status === 'yes';
289
+ isConnected = (await (await fetch(_areYouOk(projectUrl))).json(), { cache: 'no-cache', credentials: 'omit' }).status === 'yes';
289
290
  } catch (_) { }
290
291
 
291
292
  if (!isConnected)
@@ -435,7 +435,7 @@ const hydrateForeignDoc = ({ data, doc_holder }) => {
435
435
  if (v?._foreign_doc) {
436
436
  v._foreign_doc = Array.isArray(v._foreign_doc)
437
437
  ? v._foreign_doc.map(k => doc_holder[k])
438
- : doc_holder[k];
438
+ : doc_holder[v._foreign_doc];
439
439
  }
440
440
  return v;
441
441
  });
@@ -505,8 +505,11 @@ const findObject = async (builder, config) => {
505
505
  Scoped.PendingDbReadCollective[processAccessId] = [];
506
506
  }
507
507
 
508
- const staleData = await getRecordData();
509
- if (retrieval.startsWith('sticky') && staleData) {
508
+ let staleData;
509
+ if (
510
+ retrieval.startsWith('sticky') &&
511
+ (staleData = await getRecordData())
512
+ ) {
510
513
  finalize(staleData);
511
514
  if (retrieval !== RETRIEVAL.STICKY_RELOAD) return;
512
515
  }
@@ -6,16 +6,16 @@ import { incrementFetcherSize } from "./counter";
6
6
 
7
7
  export const insertFetchResources = async (projectUrl, access_id, value) => {
8
8
  value = cloneDeep(value);
9
- const data = serialize(value).toString('base64');
9
+ const dataSize = serialize(value).byteLength;
10
10
 
11
11
  if (!CacheStore.FetchedStore[projectUrl])
12
12
  CacheStore.FetchedStore[projectUrl] = {};
13
13
  const b4 = CacheStore.FetchedStore[projectUrl][access_id];
14
- incrementFetcherSize(projectUrl, data.length - (b4?.size || 0));
14
+ incrementFetcherSize(projectUrl, dataSize - (b4?.size || 0));
15
15
  CacheStore.FetchedStore[projectUrl][access_id] = {
16
16
  touched: Date.now(),
17
17
  data: value,
18
- size: data.length
18
+ size: dataSize
19
19
  };
20
20
 
21
21
  updateCacheStore(undefined, ['FetchedStore']);
@@ -126,8 +126,11 @@ export const mfetch = async (input = '', init, config) => {
126
126
  Scoped.PendingFetchCollective[processReqId] = [];
127
127
  }
128
128
 
129
- const reqData = await getFetchResources(projectUrl, reqId);
130
- if (retrieval.startsWith('sticky') && reqData) {
129
+ let reqData;
130
+ if (
131
+ retrieval.startsWith('sticky') &&
132
+ (reqData = await getFetchResources(projectUrl, reqId))
133
+ ) {
131
134
  resolveCache(reqData);
132
135
  if (retrieval !== RETRIEVAL.STICKY_RELOAD) return;
133
136
  }
@@ -144,6 +147,7 @@ export const mfetch = async (input = '', init, config) => {
144
147
 
145
148
  const f = await fetch(isLink ? input : `${projectUrl}/${normalizeRoute(input)}`, {
146
149
  ...(!isBaseUrl || hasBody) ? { method: 'POST' } : {},
150
+ credentials: 'omit',
147
151
  ...init,
148
152
  ...uglified ? { body: reqBuilder } : encodeBody ? { body: serialize(body) } : {},
149
153
  // cache: 'no-cache',
@@ -154,7 +158,9 @@ export const mfetch = async (input = '', init, config) => {
154
158
  uglified,
155
159
  'content-type': 'request/buffer',
156
160
  ...initType ? { 'init-content-type': initType } : {}
157
- } : {},
161
+ } : encodeBody
162
+ ? { 'content-type': 'request/buffer', 'entity-encoded': '1' }
163
+ : {},
158
164
  ...(disableAuth || !mtoken || uglified || isBaseUrl) ? {} : { mtoken }
159
165
  }
160
166
  });
@@ -43,7 +43,7 @@ export class MTStorage {
43
43
  return () => { };
44
44
  }
45
45
 
46
- const { projectUrl, accessKey, uglify } = this.builder;
46
+ const { projectUrl, uglify, extraHeaders } = this.builder;
47
47
  xhr = new XMLHttpRequest();
48
48
 
49
49
  if (awaitServer) await awaitReachableServer(projectUrl);
@@ -51,7 +51,7 @@ export class MTStorage {
51
51
 
52
52
  xhr.open('POST', EngineApi._uploadFile(projectUrl, uglify), true);
53
53
  xhr.upload.addEventListener('progress', e => {
54
- onProgress?.({ sentBtyes: e.loaded, totalBytes: e.total });
54
+ onProgress?.({ sentBytes: e.loaded, totalBytes: e.total });
55
55
  });
56
56
  xhr.addEventListener('load', () => {
57
57
  if (hasFinished || hasCancelled) return;
@@ -75,12 +75,17 @@ export class MTStorage {
75
75
  hasFinished = true;
76
76
  onComplete?.({ error: 'upload_aborted', message: 'The upload process was aborted' });
77
77
  });
78
- xhr.setRequestHeader('Accept', 'application/json');
78
+
79
+ Object.entries(extraHeaders || {}).forEach(([k, v]) => {
80
+ xhr.setRequestHeader(k, v);
81
+ });
82
+
79
83
  xhr.setRequestHeader('Content-Type', 'buffer/upload');
80
84
  if (Scoped.AuthJWTToken[projectUrl])
81
85
  xhr.setRequestHeader('Mosquito-Token', Scoped.AuthJWTToken[projectUrl]);
82
86
  if (createHash) xhr.setRequestHeader('hash-upload', 'yes');
83
87
  xhr.setRequestHeader('Mosquito-Destination', destination);
88
+ xhr.withCredentials = false;
84
89
  xhr.send(fileStream || buffer);
85
90
  })();
86
91