react-native-mosquito-transport 0.0.46 → 0.0.48

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
@@ -25,3 +25,11 @@
25
25
  - transform undefined to void instead of null
26
26
  - add metadata to provider auth login
27
27
  <!-- - error: "refreshToken retry limit exceeded" <--- no need -->
28
+
29
+ - _areYouOk() should timeout max 5000
30
+ - .json() should be parse nicely
31
+ - when server is offline and suddenly comes online, fetchHttp throw some error
32
+ - string to Buffer may be in utf16
33
+
34
+ # changes made
35
+ storage uploadFile method and others
@@ -95,7 +95,7 @@ class MosquitodbUploadTask: NSObject, URLSessionDataDelegate {
95
95
  var request = URLRequest(url: URL(string: url)!)
96
96
  request.httpMethod = "POST"
97
97
 
98
- if let extraHeaders = options["extraHeaders"] as? [[String: String]] {
98
+ if let extraHeaders = options["extraHeaders"] as? [String: String] {
99
99
  for (key, value) in extraHeaders {
100
100
  request.setValue(value, forHTTPHeaderField: key)
101
101
  }
@@ -191,7 +191,7 @@ class MosquitodbDownloadTask: NSObject, URLSessionDownloadDelegate {
191
191
  var request = URLRequest(url: URL(string: url)!)
192
192
  request.httpMethod = "POST"
193
193
 
194
- if let extraHeaders = options["extraHeaders"] as? [[String: String]] {
194
+ if let extraHeaders = options["extraHeaders"] as? [String: String] {
195
195
  for (key, value) in extraHeaders {
196
196
  request.setValue(value, forHTTPHeaderField: key)
197
197
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mosquito-transport",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
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",
@@ -29,12 +29,12 @@
29
29
  "dependencies": {
30
30
  "@turf/turf": "^7.2.0",
31
31
  "buffer": "^6.0.3",
32
- "entity-serializer": "^1.0.3",
32
+ "entity-serializer": "^1.0.4",
33
33
  "guard-object": "^1.1.4",
34
34
  "poke-object": "^1.0.1",
35
35
  "simplify-error": "^1.0.1",
36
36
  "socket.io-client": "^4.8.1",
37
- "subscription-listener": "^1.1.2",
37
+ "subscription-listener": "^1.1.3",
38
38
  "tweetnacl": "^1.0.3"
39
39
  },
40
40
  "peerDependencies": {
@@ -10,10 +10,10 @@ const { box, randomBytes } = naclPkg;
10
10
 
11
11
  export const listenReachableServer = (callback, projectUrl) => {
12
12
  let lastValue;
13
- return ServerReachableListener.listenTo(projectUrl, t => {
13
+ return ServerReachableListener.listenToPersist(projectUrl, t => {
14
14
  if (typeof t === 'boolean' && t !== lastValue) callback?.(t);
15
15
  lastValue = t;
16
- }, true);
16
+ });
17
17
  };
18
18
 
19
19
  export const prefixStoragePath = (path, prefix = 'file:///') => {
@@ -134,7 +134,7 @@ export const releaseCacheStore = async (builder) => {
134
134
  Scoped.AuthJWTToken[key] = value?.token;
135
135
  });
136
136
  Scoped.IsStoreReady = true;
137
- StoreReadyListener.dispatch('_', 'ready');
137
+ StoreReadyListener.dispatchPersist('_', 'ready');
138
138
  setTimeout(() => {
139
139
  if (tobePurged.length) updateCacheStore(tobePurged);
140
140
  }, 0);
@@ -147,12 +147,12 @@ export const awaitStore = () => new Promise(resolve => {
147
147
  resolve();
148
148
  return;
149
149
  }
150
- const l = StoreReadyListener.listenTo('_', t => {
150
+ const l = StoreReadyListener.listenToPersist('_', t => {
151
151
  if (t === 'ready') {
152
152
  resolve();
153
153
  l();
154
154
  }
155
- }, true);
155
+ });
156
156
  });
157
157
 
158
158
  export const awaitReachableServer = (projectUrl) => new Promise(resolve => {
@@ -160,12 +160,12 @@ export const awaitReachableServer = (projectUrl) => new Promise(resolve => {
160
160
  resolve();
161
161
  return;
162
162
  }
163
- const l = ServerReachableListener.listenTo(projectUrl, t => {
163
+ const l = ServerReachableListener.listenToPersist(projectUrl, t => {
164
164
  if (t) {
165
165
  resolve();
166
166
  l();
167
167
  }
168
- }, true);
168
+ });
169
169
  });
170
170
 
171
171
  export const getReachableServer = (projectUrl) => new Promise(resolve => {
@@ -173,12 +173,12 @@ export const getReachableServer = (projectUrl) => new Promise(resolve => {
173
173
  resolve(Scoped.IS_CONNECTED[projectUrl]);
174
174
  return;
175
175
  }
176
- const l = ServerReachableListener.listenTo(projectUrl, t => {
176
+ const l = ServerReachableListener.listenToPersist(projectUrl, t => {
177
177
  if (typeof t === 'boolean') {
178
178
  resolve(t);
179
179
  l();
180
180
  }
181
- }, true);
181
+ });
182
182
  });
183
183
 
184
184
  export const buildFetchInterface = async ({ body, authToken, method, uglify, serverE2E_PublicKey, extraHeaders }) => {
package/src/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { BSON } from "./vendor/bson";
2
2
 
3
- interface RNMTConfig {
3
+ export interface RNMTConfig {
4
4
  dbName?: string;
5
5
  dbUrl?: string;
6
6
  projectUrl: string;
@@ -38,7 +38,7 @@ interface RNMTConfig {
38
38
  castBSON?: boolean;
39
39
  }
40
40
 
41
- interface GetDatabase {
41
+ export interface GetDatabase {
42
42
  collection: (path: string) => RNMTCollection;
43
43
  }
44
44
 
@@ -98,7 +98,7 @@ type auth_provider_id_values = auth_provider_id['GOOGLE'] |
98
98
  interface ReleaseCacheOption_IO {
99
99
  }
100
100
 
101
- interface ReleaseCacheOption {
101
+ export interface ReleaseCacheOption {
102
102
  /**
103
103
  * fs is used as the default caching mechanism
104
104
  *
@@ -137,7 +137,7 @@ interface ReleaseCacheOption {
137
137
  promoteCache?: boolean;
138
138
  }
139
139
 
140
- interface RNMTSocket {
140
+ export interface RNMTSocket {
141
141
  timeout: (timeout?: number) => ({
142
142
  emitWithAck: (...args: any) => Promise<any>;
143
143
  });
@@ -167,13 +167,18 @@ interface CountConfig {
167
167
  disableAuth?: boolean;
168
168
  }
169
169
 
170
- interface FetchHttpResponse extends Response {
170
+ export interface FetchHttpResponse extends Response {
171
171
  /**
172
172
  * true if this response was from local cache
173
173
  */
174
174
  fromCache?: boolean | undefined;
175
175
  }
176
176
 
177
+ interface CustomSocketOption extends OveridenProjectUrl {
178
+ disableAuth?: boolean;
179
+ authHandshake?: Object;
180
+ }
181
+
177
182
  export default class RNMT {
178
183
  constructor(config: RNMTConfig);
179
184
  static initializeCache(option?: ReleaseCacheOption): void;
@@ -183,12 +188,12 @@ export default class RNMT {
183
188
  storage(): RNMTStorage;
184
189
  fetchHttp(endpoint: string, init?: RequestInit, config?: FetchHttpConfig): Promise<FetchHttpResponse>;
185
190
  listenReachableServer(callback: (reachable: boolean) => void): () => void;
186
- getSocket(options: { disableAuth?: boolean; authHandshake?: Object }): RNMTSocket;
191
+ getSocket(options?: CustomSocketOption): RNMTSocket;
187
192
  onConnect: () => CollectionIO;
188
193
  batchWrite(map: BatchWriteValue[], config?: BatchWriteConfig): Promise<DocumentWriteResult[] | undefined>;
189
194
  }
190
195
 
191
- interface RNMTCollection {
196
+ export interface RNMTCollection {
192
197
  find: (find?: DocumentFind) => ({
193
198
  get: (config?: GetConfig) => Promise<DocumentResult[]>;
194
199
  listen: (callback: (snapshot?: DocumentResult[]) => void, onError?: (error?: DocumentError) => void, config?: GetConfig) => void;
@@ -258,7 +263,7 @@ interface RNMTCollection {
258
263
  deleteMany: (find?: DocumentFind, config?: WriteConfig) => Promise<DocumentWriteResult>;
259
264
  }
260
265
 
261
- interface CollectionTaskIO<T> {
266
+ export interface CollectionTaskIO<T> {
262
267
  batchWrite(map: BatchWriteValue[], config?: BatchWriteConfig): T;
263
268
  }
264
269
 
@@ -270,7 +275,7 @@ interface OnConnectChain extends StartStop {
270
275
  onDisconnect: () => CollectionTaskIO<StartStop>;
271
276
  }
272
277
 
273
- interface CollectionIO extends CollectionTaskIO<OnConnectChain> {
278
+ export interface CollectionIO extends CollectionTaskIO<OnConnectChain> {
274
279
  onDisconnect: () => CollectionTaskIO<StartStop>;
275
280
  }
276
281
 
@@ -282,7 +287,7 @@ interface DocumentError extends ErrorResponse {
282
287
 
283
288
  }
284
289
 
285
- interface FetchHttpConfig {
290
+ export interface FetchHttpConfig {
286
291
  retrieval?: GetConfig['retrieval'];
287
292
  /**
288
293
  * disable sending authentication token along with this request
@@ -429,11 +434,16 @@ interface DocumentWriteValue {
429
434
 
430
435
  }
431
436
 
432
- interface RNMTAuth {
437
+ export interface RNMTAuth {
433
438
  customSignin: (email: string, password: string) => Promise<SigninResult>;
434
439
  customSignup: (email: string, password: string, name?: string, metadata?: Object) => Promise<SignupResult>;
435
- googleSignin: (token: string) => Promise<SignupResult>;
436
- appleSignin: () => Promise<SignupResult>;
440
+ /**
441
+ *
442
+ * @param token can be an `id_token` or `authorization code` returned from Google Identity Services
443
+ * @param metadata
444
+ */
445
+ googleSignin: (token: string, metadata?: any | undefined) => Promise<SignupResult>;
446
+ appleSignin: (id_token: string, metadata?: any | undefined) => Promise<SignupResult>;
437
447
  facebookSignin: () => Promise<SignupResult>;
438
448
  twitterSignin: () => Promise<SignupResult>;
439
449
  githubSignin: () => Promise<SignupResult>;
@@ -460,7 +470,7 @@ export interface SignupResult extends SigninResult {
460
470
  isNewUser: boolean;
461
471
  }
462
472
 
463
- interface AuthData {
473
+ export interface AuthData {
464
474
  email?: string;
465
475
  metadata: Object;
466
476
  signupMethod: auth_provider_id_values;
@@ -468,7 +478,8 @@ interface AuthData {
468
478
  joinedOn: number;
469
479
  uid: string;
470
480
  claims: Object;
471
- emailVerified: boolean;
481
+ authVerified: boolean;
482
+ passwordVerified?: boolean | undefined;
472
483
  tokenID: string;
473
484
  disabled: boolean;
474
485
  entityOf: string;
@@ -482,7 +493,7 @@ interface AuthData {
482
493
  sub: string;
483
494
  }
484
495
 
485
- interface RefreshTokenData {
496
+ export interface RefreshTokenData {
486
497
  uid: string;
487
498
  tokenID: string;
488
499
  isRefreshToken: true;
@@ -492,24 +503,37 @@ interface RefreshTokenData {
492
503
  sub: string;
493
504
  }
494
505
 
495
- interface TokenEventData extends AuthData {
506
+ export interface TokenEventData extends AuthData {
496
507
  tokenManager: TokenManager;
497
508
  }
498
509
 
499
- interface TokenManager {
510
+ export interface TokenManager {
500
511
  refreshToken: string;
501
512
  accessToken: string;
502
513
  }
503
514
 
504
- interface UploadOptions {
515
+ interface OveridenProjectUrl {
516
+ /**
517
+ * The server instance to send requests to. This overrides the parent `projectUrl`, but still relies on the parent `projectUrl` for authentication token resolution and verify server reachability.
518
+ */
519
+ projectUrl?: string;
520
+ }
521
+
522
+ interface UploadOptions extends OveridenProjectUrl {
505
523
  /**
506
524
  * optionally create hash for this upload to save disk space
507
525
  */
508
526
  createHash?: boolean;
527
+
509
528
  /**
510
529
  * wait for a reachable server before initiating the upload task
511
530
  */
512
531
  awaitServer?: boolean;
532
+
533
+ /**
534
+ * monitor upload progress stats
535
+ */
536
+ onProgress?: (stats: UploadProgressStats) => void;
513
537
  }
514
538
 
515
539
  interface DownloadOptions {
@@ -517,16 +541,28 @@ interface DownloadOptions {
517
541
  * wait for a reachable server before initiating the download task
518
542
  */
519
543
  awaitServer?: boolean;
544
+
545
+ /**
546
+ * monitor download progress stats
547
+ */
548
+ onProgress?: (stats: DownloadProgressStats) => void;
549
+ }
550
+
551
+ interface StorageTask extends Promise<string> {
552
+ /**
553
+ * abort the running task process
554
+ */
555
+ abort: () => void;
520
556
  }
521
557
 
522
- interface RNMTStorage {
523
- downloadFile: (link: string, onComplete?: (error?: ErrorResponse, filepath?: string) => void, destination?: string, onProgress?: (stats: DownloadProgressStats) => void, options?: DownloadOptions) => () => void;
524
- uploadFile: (file: string, destination: string, onComplete?: (error?: ErrorResponse, downloadUrl?: string) => void, onProgress?: (stats: UploadProgressStats) => void, options?: UploadOptions) => () => void;
525
- deleteFile: (path: string) => Promise<void>;
526
- deleteFolder: (folder: string) => Promise<void>;
558
+ export interface RNMTStorage {
559
+ downloadFile: (link: string, filepath?: string | undefined, options?: DownloadOptions | undefined) => StorageTask;
560
+ uploadFile: (filepath: string, destination: string, options?: UploadOptions | undefined) => StorageTask;
561
+ deleteFile: (path: string, options?: OveridenProjectUrl | undefined) => Promise<void>;
562
+ deleteFolder: (folder: string, options?: OveridenProjectUrl | undefined) => Promise<void>;
527
563
  }
528
564
 
529
- interface DownloadProgressStats {
565
+ export interface DownloadProgressStats {
530
566
  receivedBtyes: number;
531
567
  expectedBytes: number;
532
568
  isPaused: boolean;
package/src/index.js CHANGED
@@ -79,7 +79,7 @@ class RNMT {
79
79
  isConnected = true;
80
80
  Scoped.IS_CONNECTED[projectUrl] = true;
81
81
  if (recentToken) updateMountedToken();
82
- ServerReachableListener.dispatch(projectUrl, true);
82
+ ServerReachableListener.dispatchPersist(projectUrl, true);
83
83
  awaitStore().then(() => {
84
84
  if (isConnected) trySendPendingWrite(projectUrl);
85
85
  });
@@ -88,7 +88,7 @@ class RNMT {
88
88
  ++connectionIte;
89
89
  isConnected = false;
90
90
  Scoped.IS_CONNECTED[projectUrl] = false;
91
- ServerReachableListener.dispatch(projectUrl, false);
91
+ ServerReachableListener.dispatchPersist(projectUrl, false);
92
92
  }
93
93
 
94
94
  const manualCheckConnection = () => {
@@ -165,7 +165,7 @@ class RNMT {
165
165
  listenReachableServer = (callback) => listenReachableServer(callback, this.config.projectUrl);
166
166
 
167
167
  getSocket = (configOpts) => {
168
- const { disableAuth, authHandshake } = configOpts || {};
168
+ const { disableAuth, authHandshake, projectUrl: overidenUrl } = configOpts || {};
169
169
  const { projectUrl, uglify, serverE2E_PublicKey, wsPrefix, extraHeaders } = this.config;
170
170
 
171
171
  const restrictedRoute = [
@@ -278,7 +278,10 @@ class RNMT {
278
278
  const mtoken = disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl];
279
279
  const [reqBuilder, [privateKey]] = uglify ? await serializeE2E({ a_extras: authHandshake }, mtoken, serverE2E_PublicKey) : [null, []];
280
280
 
281
- socket = io(`${wsPrefix}://${projectUrl.split('://')[1]}`, {
281
+ const getWsPrefix = url => url.startsWith('https') ? 'wss' : 'ws';
282
+ const wsUrl = overidenUrl ? `${getWsPrefix(overidenUrl)}://${overidenUrl.split('://')[1]}` : `${wsPrefix}://${projectUrl.split('://')[1]}`;
283
+
284
+ socket = io(wsUrl, {
282
285
  transports: ['websocket', 'polling', 'flashsocket'],
283
286
  extraHeaders,
284
287
  auth: uglify ? {
@@ -1,4 +1,4 @@
1
- import { doSignOut, revokeAuthIntance } from ".";
1
+ 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, listenReachableServer } from "../../helpers/peripherals";
@@ -9,10 +9,10 @@ import { Validator } from "guard-object";
9
9
  import { basicClone } from "../../helpers/basic_clone";
10
10
 
11
11
  export const listenToken = (callback, projectUrl) =>
12
- AuthTokenListener.listenTo(projectUrl, (t, n) => {
12
+ AuthTokenListener.listenToPersist(projectUrl, (t, n) => {
13
13
  if (t === undefined) return;
14
14
  callback?.(t || null, n);
15
- }, true);
15
+ });
16
16
 
17
17
  export const injectFreshToken = async (config, { token, refreshToken }) => {
18
18
  const { projectUrl } = config;
@@ -56,19 +56,19 @@ export const parseToken = (token) => JSON.parse(decodeBinary(token.split('.')[1]
56
56
 
57
57
  export const triggerAuthToken = async (projectUrl, isInit) => {
58
58
  await awaitStore();
59
- AuthTokenListener.dispatch(projectUrl, CacheStore.AuthStore[projectUrl]?.token || null, isInit);
59
+ AuthTokenListener.dispatchPersist(projectUrl, CacheStore.AuthStore[projectUrl]?.token || null, isInit);
60
60
  };
61
61
 
62
62
  export const awaitRefreshToken = (projectUrl) => new Promise(resolve => {
63
- const l = TokenRefreshListener.listenTo(projectUrl, v => {
63
+ const l = TokenRefreshListener.listenToPersist(projectUrl, v => {
64
64
  if (v === 'ready') {
65
65
  l();
66
66
  resolve();
67
67
  }
68
- }, true);
68
+ });
69
69
  });
70
70
 
71
- export const listenTokenReady = (callback, projectUrl) => TokenRefreshListener.listenTo(projectUrl, callback, true);
71
+ export const listenTokenReady = (callback, projectUrl) => TokenRefreshListener.listenToPersist(projectUrl, callback);
72
72
 
73
73
  export const initTokenRefresher = async (config, forceRefresh) => {
74
74
  const { projectUrl, maxRetries } = config;
@@ -81,9 +81,9 @@ export const initTokenRefresher = async (config, forceRefresh) => {
81
81
  if (emulatedURL) return;
82
82
 
83
83
  const notifyAuthReady = (value) => {
84
- TokenRefreshListener.dispatch(projectUrl, value);
84
+ TokenRefreshListener.dispatchPersist(projectUrl, value);
85
85
  getEmulatedLinks(projectUrl).forEach(v => {
86
- TokenRefreshListener.dispatch(v, value);
86
+ TokenRefreshListener.dispatchPersist(v, value);
87
87
  });
88
88
  }
89
89
 
@@ -14,6 +14,7 @@ const {
14
14
  _customSignin,
15
15
  _customSignup,
16
16
  _googleSignin,
17
+ _appleSignin,
17
18
  _areYouOk
18
19
  } = EngineApi;
19
20
 
@@ -28,9 +29,7 @@ export default class MTAuth {
28
29
 
29
30
  googleSignin = (token, metadata) => doGoogleSignin(this.builder, token, metadata);
30
31
 
31
- appleSignin() {
32
- throw 'unsupported method call';
33
- }
32
+ appleSignin = (token, metadata) => doAppleSignin(this.builder, token, metadata);
34
33
 
35
34
  facebookSignin() {
36
35
  throw 'unsupported method call';
@@ -240,7 +239,7 @@ const purgeCache = (url, isMain) => {
240
239
  ].forEach(e => {
241
240
  if (e && CacheStore[e]?.[url]) delete CacheStore[e][url];
242
241
  });
243
- TokenRefreshListener.dispatch(url);
242
+ TokenRefreshListener.dispatchPersist(url);
244
243
  triggerAuthToken(url);
245
244
  };
246
245
 
@@ -255,11 +254,13 @@ const clearCacheForSignout = (builder, disposeEmulated) => {
255
254
  export const doSignOut = async (builder) => {
256
255
  if (!Scoped.IsStoreReady) await awaitStore();
257
256
  const emulatedURL = CacheStore.EmulatedAuth[builder.projectUrl];
257
+ const thisAuthStore = emulatedURL ? undefined : basicClone(CacheStore.AuthStore[builder.projectUrl]);
258
258
 
259
259
  clearCacheForSignout(builder, !emulatedURL);
260
260
  updateCacheStore(['AuthStore', 'EmulatedAuth']);
261
261
  if (emulatedURL) return;
262
- await revokeAuthIntance(builder);
262
+
263
+ await revokeAuthIntance(builder, thisAuthStore);
263
264
  };
264
265
 
265
266
  export const revokeAuthIntance = async (builder, authStore) => {
@@ -289,8 +290,7 @@ export const purgePendingToken = async (nodeId) => {
289
290
  isConnected = (await (await fetch(_areYouOk(projectUrl), { credentials: 'omit' })).json()).status === 'yes';
290
291
  } catch (_) { }
291
292
 
292
- if (!isConnected)
293
- await awaitReachableServer(projectUrl);
293
+ if (!isConnected) await awaitReachableServer(projectUrl);
294
294
 
295
295
  const [reqBuilder] = await buildFetchInterface({
296
296
  body: { token, r_token },
@@ -308,7 +308,10 @@ export const purgePendingToken = async (nodeId) => {
308
308
  }
309
309
  };
310
310
 
311
- const doGoogleSignin = (builder, token, metadata) => new Promise(async (resolve, reject) => {
311
+ const doGoogleSignin = (builder, token, metadata) => doProviderSignin(builder, token, metadata, _googleSignin);
312
+ const doAppleSignin = (builder, token, metadata) => doProviderSignin(builder, token, metadata, _appleSignin);
313
+
314
+ const doProviderSignin = (builder, token, metadata, endpointer) => new Promise(async (resolve, reject) => {
312
315
  const { projectUrl, serverE2E_PublicKey, uglify, extraHeaders } = builder;
313
316
 
314
317
  try {
@@ -322,7 +325,7 @@ const doGoogleSignin = (builder, token, metadata) => new Promise(async (resolve,
322
325
  extraHeaders
323
326
  });
324
327
 
325
- const data = await buildFetchResult(await fetch(_googleSignin(projectUrl, uglify), reqBuilder), uglify);
328
+ const data = await buildFetchResult(await fetch(endpointer(projectUrl, uglify), reqBuilder), uglify);
326
329
 
327
330
  const f = uglify ? await deserializeE2E(data, serverE2E_PublicKey, privateKey) : data;
328
331
 
@@ -337,8 +340,4 @@ const doGoogleSignin = (builder, token, metadata) => new Promise(async (resolve,
337
340
  } catch (e) {
338
341
  reject(simplifyCaughtError(e).simpleError);
339
342
  }
340
- });
341
-
342
- const doAppleSignin = async () => {
343
-
344
- }
343
+ });
@@ -3,7 +3,7 @@ import { deserializeE2E, listenReachableServer, niceHash, normalizeRoute, serial
3
3
  import { awaitStore, getReachableServer } from "../../helpers/utils";
4
4
  import { RETRIEVAL } from "../../helpers/values";
5
5
  import { Scoped } from "../../helpers/variables";
6
- import { awaitRefreshToken } from "../auth/accessor";
6
+ import { awaitRefreshToken, 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";
@@ -71,17 +71,18 @@ export const mfetch = async (input = '', init, config) => {
71
71
  ) throw `"body" must be any of string, buffer, object`;
72
72
  }
73
73
  await awaitStore();
74
+ const thisToken = disableAuth ? '' : (Scoped.AuthJWTToken[projectUrl] || '');
74
75
 
75
76
  const reqId = await niceHash(
76
77
  serialize([
77
78
  rawHeader,
78
79
  body,
79
- !!disableAuth,
80
+ // !!disableAuth,
80
81
  input,
81
- disableAuth ? '' : (Scoped.AuthJWTToken[projectUrl] || '')
82
+ thisToken && await parseToken(thisToken).uid
82
83
  ]).toString('base64')
83
84
  );
84
- const processReqId = `${reqId}_${disableCache}_${retrieval}`;
85
+ const processReqId = `${reqId}_${thisToken}_${disableCache}_${retrieval}`;
85
86
 
86
87
  let retries = 0, hasFinalize;
87
88
 
@@ -143,7 +144,7 @@ export const mfetch = async (input = '', init, config) => {
143
144
  const [reqBuilder, [privateKey]] = uglified ? await serializeE2E(body, mtoken, serverE2E_PublicKey) : [null, []];
144
145
 
145
146
  const f = await fetch(isLink ? input : `${projectUrl}/${normalizeRoute(input)}`, {
146
- ...(encodeBody || uglified) ? { method: 'POST' } : {},
147
+ ...(hasBody || uglified) ? { method: 'POST' } : {},
147
148
  credentials: 'omit',
148
149
  ...init,
149
150
  ...uglified ? { body: reqBuilder } : encodeBody ? { body: serialize(body) } : {},
@@ -5,6 +5,7 @@ import { DeviceEventEmitter, NativeEventEmitter, NativeModules, Platform } from
5
5
  import { awaitReachableServer, buildFetchInterface, buildFetchResult } from "../../helpers/utils";
6
6
  import { awaitRefreshToken } from "../auth/accessor";
7
7
  import { simplifyError } from "simplify-error";
8
+ import { Validator } from "guard-object";
8
9
 
9
10
  const LINKING_ERROR =
10
11
  `The package 'react-native-mosquito-transport' doesn't seem to be linked. Make sure: \n\n` +
@@ -19,6 +20,7 @@ const RNMTModule = NativeModules.Mosquitodb || (
19
20
  },
20
21
  })
21
22
  );
23
+
22
24
  const emitter = Platform.OS === 'android' ?
23
25
  DeviceEventEmitter : new NativeEventEmitter(RNMTModule);
24
26
 
@@ -27,26 +29,43 @@ export class MTStorage {
27
29
  this.builder = { ...config };
28
30
  }
29
31
 
30
- downloadFile(link = '', onComplete, destination, onProgress, options) {
31
- const { awaitServer } = options || {};
32
+ downloadFile = (link = '', destination, options) => {
33
+ const { awaitServer, onProgress } = options || {};
32
34
  let hasFinished, isPaused, hasCancelled;
33
35
 
34
36
  const { projectUrl, extraHeaders } = this.builder;
37
+ let onComplete;
38
+
39
+ const promise = new Promise((resolve, reject) => {
40
+ onComplete = (err, path) => {
41
+ if (hasFinished) return;
42
+ hasFinished = true;
43
+ if (path) {
44
+ resolve(path);
45
+ } else reject(err);
46
+ }
47
+ });
48
+
49
+ promise.abort = () => {
50
+ if (hasFinished || hasCancelled) return;
51
+ RNMTModule.cancelDownload(processID);
52
+ hasCancelled = true;
53
+ onComplete?.({ error: 'download_aborted', message: 'The download process was aborted' });
54
+ }
35
55
 
36
56
  if (destination && (typeof destination !== 'string' || !destination.trim())) {
37
57
  onComplete?.({ error: 'destination_invalid', message: 'destination must be a non-empty string' });
38
- return () => { };
58
+ return promise;
39
59
  }
40
60
  if (destination) destination = prefixStoragePath(destination?.trim());
41
61
 
42
- if (typeof link !== 'string' || !link.trim().startsWith(`${EngineApi.staticStorage(projectUrl)}/`)) {
62
+ if (typeof link !== 'string' || !Validator.LINK(link = link.trim())) {
43
63
  onComplete?.({
44
64
  error: 'invalid_link',
45
- message: `link has an invalid value, expected a string that starts with "${EngineApi.staticStorage(projectUrl)}/"`
65
+ message: `downloadFile first argument has an invalid value, expected a valid link string but got '${link}' instead`
46
66
  });
47
- return () => { };
67
+ return promise;
48
68
  }
49
- link = link.trim();
50
69
 
51
70
  const processID = `${++Scoped.StorageProcessID}`;
52
71
  const init = async () => {
@@ -86,7 +105,6 @@ export class MTStorage {
86
105
  onComplete?.(path ? undefined : (result?.simpleError || { error, message: errorDes }), path);
87
106
  resultListener.remove();
88
107
  progressListener.remove();
89
- hasFinished = true;
90
108
  });
91
109
 
92
110
  RNMTModule.downloadFile({
@@ -103,30 +121,36 @@ export class MTStorage {
103
121
  }
104
122
 
105
123
  init();
106
-
107
- return () => {
108
- if (hasFinished || hasCancelled) return;
109
- RNMTModule.cancelDownload(processID);
110
- hasCancelled = true;
111
- setTimeout(() => {
112
- onComplete?.({ error: 'download_aborted', message: 'The download process was aborted' });
113
- }, 1);
114
- }
124
+ return promise;
115
125
  }
116
126
 
117
- uploadFile(file = '', destination = '', onComplete, onProgress, options) {
118
- const { createHash, awaitServer } = options || {};
127
+ uploadFile = (file = '', destination = '', options) => {
128
+ const { createHash, awaitServer, onProgress } = options || {};
119
129
  let hasFinished, hasCancelled;
130
+ let thisComplete;
120
131
 
121
- const thisComplete = (...args) => {
122
- if (hasFinished) return;
123
- hasFinished = true;
124
- onComplete?.(...args);
125
- }
132
+ const promise = new Promise((resolve, reject) => {
133
+ thisComplete = (err, url) => {
134
+ if (hasFinished) return;
135
+ hasFinished = true;
136
+ if (url) {
137
+ resolve(url);
138
+ } else reject(err);
139
+ }
140
+ });
141
+
142
+ promise.abort = () => {
143
+ if (hasFinished || hasCancelled) return;
144
+ hasCancelled = true;
145
+ setTimeout(() => {
146
+ thisComplete?.({ error: 'upload_aborted', message: 'The upload process was aborted' });
147
+ }, 0);
148
+ RNMTModule.cancelUpload(processID);
149
+ };
126
150
 
127
151
  if (typeof file !== 'string' || !file.trim()) {
128
152
  thisComplete?.({ error: 'file_path_invalid', message: 'file must be a non-empty string in uploadFile()' });
129
- return () => { };
153
+ return promise;
130
154
  }
131
155
  destination = destination?.trim?.();
132
156
 
@@ -134,7 +158,7 @@ export class MTStorage {
134
158
  validateDestination(destination);
135
159
  } catch (error) {
136
160
  thisComplete?.({ error: 'destination_invalid', message: error });
137
- return () => { };
161
+ return promise;
138
162
  }
139
163
 
140
164
  const isAsset = file.startsWith('ph://') || file.startsWith('content://');
@@ -142,6 +166,7 @@ export class MTStorage {
142
166
 
143
167
  const { projectUrl, uglify, extraHeaders } = this.builder;
144
168
  const processID = `${++Scoped.StorageProcessID}`;
169
+ const thisProjectUrl = options?.projectUrl || projectUrl;
145
170
 
146
171
  const init = async () => {
147
172
  if (awaitServer) await awaitReachableServer(projectUrl);
@@ -167,7 +192,7 @@ export class MTStorage {
167
192
  const authToken = Scoped.AuthJWTToken[projectUrl];
168
193
 
169
194
  RNMTModule.uploadFile({
170
- url: EngineApi._uploadFile(projectUrl, uglify),
195
+ url: EngineApi._uploadFile(thisProjectUrl, uglify),
171
196
  file: isAsset ? file : file.substring('file://'.length),
172
197
  ...authToken ? { authToken } : {},
173
198
  createHash: createHash ? 'yes' : 'no',
@@ -178,24 +203,16 @@ export class MTStorage {
178
203
  }
179
204
 
180
205
  init();
181
-
182
- return () => {
183
- if (hasFinished || hasCancelled) return;
184
- hasCancelled = true;
185
- setTimeout(() => {
186
- thisComplete?.({ error: 'upload_aborted', message: 'The upload process was aborted' });
187
- }, 0);
188
- RNMTModule.cancelUpload(processID);
189
- }
206
+ return promise;
190
207
  }
191
208
 
192
- deleteFile = (path) => deleteContent(this.builder, path);
193
- deleteFolder = (path) => deleteContent(this.builder, path, true);
209
+ deleteFile = (path, options) => deleteContent(this.builder, path, options);
210
+ deleteFolder = (path, options) => deleteContent(this.builder, path, options, true);
194
211
  }
195
212
 
196
213
  const { _deleteFile, _deleteFolder } = EngineApi;
197
214
 
198
- const deleteContent = async (builder, path, isFolder) => {
215
+ const deleteContent = async (builder, path, options, isFolder) => {
199
216
  const { projectUrl, uglify, extraHeaders, serverE2E_PublicKey } = builder;
200
217
 
201
218
  try {
@@ -207,8 +224,10 @@ const deleteContent = async (builder, path, isFolder) => {
207
224
  serverE2E_PublicKey,
208
225
  uglify
209
226
  });
227
+ const thisProjectUrl = options?.projectUrl || projectUrl;
210
228
 
211
- const data = await buildFetchResult(await fetch((isFolder ? _deleteFolder : _deleteFile)(projectUrl, uglify), reqBuilder), uglify);
229
+ const res = await fetch((isFolder ? _deleteFolder : _deleteFile)(thisProjectUrl, uglify), reqBuilder);
230
+ const data = await buildFetchResult(res, uglify);
212
231
  const result = uglify ? await deserializeE2E(data, serverE2E_PublicKey, privateKey) : data;
213
232
 
214
233
  if (result.status !== 'success') throw 'operation not successful';