react-native-mosquito-transport 0.0.21 → 0.0.22

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.
@@ -1,7 +1,7 @@
1
1
  import { guardArray, GuardError, guardObject, GuardSignal, niceGuard, Validator } from "guard-object";
2
2
  import { sameInstance } from "../../helpers/peripherals";
3
3
  import { RETRIEVAL } from "../../helpers/values";
4
- import getLodash from 'lodash.get';
4
+ import getLodash from 'lodash/get';
5
5
  import { Binary, BSONRegExp, BSONSymbol, Code, DBRef, Decimal128, Double, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp, UUID } from 'bson';
6
6
  import { bboxPolygon, booleanIntersects, booleanWithin, circle, distance, polygon } from "@turf/turf";
7
7
 
@@ -0,0 +1,72 @@
1
+ import { Buffer } from "buffer";
2
+ import { updateCacheStore } from "../../helpers/utils";
3
+ import { CacheStore, Scoped } from "../../helpers/variables";
4
+ import cloneDeep from "lodash/cloneDeep";
5
+ import { deserialize, serialize } from "entity-serializer";
6
+ import { SQLITE_COMMANDS, SQLITE_PATH, useSqliteLinearAccessId } from "../../helpers/sqlite_manager";
7
+ import { incrementFetcherSize } from "./counter";
8
+
9
+ const { FETCH_RESOURCES } = SQLITE_PATH;
10
+
11
+ export const insertFetchResources = async (projectUrl, access_id, value) => {
12
+ value = cloneDeep(value);
13
+ const data = serialize(value).toString('base64');
14
+
15
+ const { io } = Scoped.ReleaseCacheData;
16
+ if (io) {
17
+ if (!CacheStore.FetchedStore[projectUrl])
18
+ CacheStore.FetchedStore[projectUrl] = {};
19
+ const b4 = CacheStore.FetchedStore[projectUrl][access_id];
20
+ incrementFetcherSize(projectUrl, data.length - (b4?.size || 0));
21
+ CacheStore.FetchedStore[projectUrl][access_id] = {
22
+ touched: Date.now(),
23
+ data: value,
24
+ size: data.length
25
+ };
26
+ } else {
27
+ const initNode = projectUrl;
28
+
29
+ await useSqliteLinearAccessId(FETCH_RESOURCES(projectUrl), access_id, 'httpFetch')(async sqlite => {
30
+ if (!Scoped.initedSqliteInstances.httpFetch[initNode]) {
31
+ Scoped.initedSqliteInstances.httpFetch[initNode] = (async () => {
32
+ await sqlite.executeSql(`CREATE TABLE IF NOT EXISTS main ( access_id TEXT PRIMARY KEY, value TEXT, touched INTEGER, size INTEGER )`).catch(() => null);
33
+ await Promise.allSettled([
34
+ sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX('main', ['access_id'])),
35
+ sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX('main', ['touched']))
36
+ ]);
37
+ })();
38
+ }
39
+
40
+ await Scoped.initedSqliteInstances.httpFetch[initNode];
41
+ const b4Data = await sqlite.executeSql(`SELECT access_id, size FROM main WHERE access_id = ?`, [access_id]).then(r =>
42
+ r[0].rows.item(0)
43
+ );
44
+ await sqlite.executeSql(
45
+ SQLITE_COMMANDS.MERGE('main', ['access_id', 'value', 'touched', 'size']),
46
+ [access_id, data, Date.now(), data.length]
47
+ );
48
+ incrementFetcherSize(projectUrl, data.length - (b4Data?.size || 0));
49
+ });
50
+ }
51
+
52
+ updateCacheStore(undefined, ['FetchedStore']);
53
+ }
54
+
55
+ export const getFetchResources = async (projectUrl, access_id) => {
56
+ const { io } = Scoped.ReleaseCacheData;
57
+
58
+ if (io) {
59
+ const record = CacheStore.FetchedStore[projectUrl]?.[access_id];
60
+ if (record) record.touched = Date.now();
61
+ return record && cloneDeep(record?.data);
62
+ }
63
+
64
+ const res = await useSqliteLinearAccessId(FETCH_RESOURCES(projectUrl), access_id, 'httpFetch')(sqlite =>
65
+ sqlite.executeSql('SELECT * FROM main WHERE access_id = ?', [access_id]).then(async r => {
66
+ const data = deserialize(Buffer.from(r[0].rows.item(0).value, 'base64'));
67
+ await sqlite.executeSql(SQLITE_COMMANDS.UPDATE_COLUMNS('main', ['touched'], 'access_id = ?'), [Date.now(), access_id]);
68
+ return data;
69
+ }).catch(() => null)
70
+ );
71
+ return res;
72
+ }
@@ -0,0 +1,11 @@
1
+ import { CacheStore } from "../../helpers/variables";
2
+ import getLodash from 'lodash/get';
3
+ import setLodash from 'lodash/set';
4
+
5
+ export const incrementFetcherSize = (projectUrl, size = 0) => incrementFetcherSizeCore(CacheStore.DatabaseStats, projectUrl, size);
6
+
7
+ export const incrementFetcherSizeCore = (baseObj, projectUrl, size = 0) => {
8
+ baseObj._fetcher_size += size;
9
+ const b4 = getLodash(baseObj.fetchers, [projectUrl], 0);
10
+ setLodash(baseObj.fetchers, [projectUrl], b4 + size);
11
+ }
@@ -1,15 +1,16 @@
1
1
  import { Buffer } from "buffer";
2
2
  import { deserializeE2E, listenReachableServer, niceHash, normalizeRoute, serializeE2E } from "../../helpers/peripherals";
3
- import { awaitStore, getReachableServer, updateCacheStore } from "../../helpers/utils";
3
+ import { awaitStore, getReachableServer } from "../../helpers/utils";
4
4
  import { RETRIEVAL } from "../../helpers/values";
5
- import { CacheStore, Scoped } from "../../helpers/variables";
5
+ import { Scoped } from "../../helpers/variables";
6
6
  import { awaitRefreshToken } from "../auth/accessor";
7
7
  import { simplifyCaughtError } from "simplify-error";
8
8
  import { guardObject, Validator } from "guard-object";
9
- import cloneDeep from "lodash.clonedeep";
9
+ import cloneDeep from "lodash/cloneDeep";
10
10
  import { serialize } from "entity-serializer";
11
+ import { getFetchResources, insertFetchResources } from "./accessor";
11
12
 
12
- const buildFetchData = (data) => {
13
+ const buildFetchData = (data, extras) => {
13
14
  const { ok, type, status, statusText, redirected, url, headers, size, base64 } = data;
14
15
 
15
16
  const response = new Response(Buffer.from(base64, 'base64'), {
@@ -20,7 +21,7 @@ const buildFetchData = (data) => {
20
21
  size
21
22
  });
22
23
 
23
- Object.entries({ ok, type, url, redirected, size })
24
+ Object.entries({ ok, type, url, redirected, size, ...extras })
24
25
  .forEach(([k, v]) => {
25
26
  if (response[k] !== v)
26
27
  Object.defineProperty(response, k, {
@@ -33,7 +34,7 @@ const buildFetchData = (data) => {
33
34
  }
34
35
 
35
36
  export const mfetch = async (input = '', init, config) => {
36
- const { projectUrl, serverE2E_PublicKey, method, maxRetries = 7, disableCache, accessKey, uglify, extraHeaders } = config;
37
+ const { projectUrl, serverE2E_PublicKey, method, maxRetries = 1, disableCache = false, uglify, extraHeaders } = config;
37
38
  const { headers, body } = init || {};
38
39
 
39
40
  if (method !== undefined)
@@ -45,24 +46,22 @@ export const mfetch = async (input = '', init, config) => {
45
46
  }).validate(method);
46
47
 
47
48
  const { retrieval = RETRIEVAL.DEFAULT, enableMinimizer, rawApproach } = method || {};
48
- const isBaseUrl = Validator.LINK(input);
49
+ const isLink = Validator.LINK(input);
50
+ const isBaseUrl = isLink || rawApproach;
49
51
  const disableAuth = method?.disableAuth || isBaseUrl;
50
- const shouldCache = (retrieval !== RETRIEVAL.DEFAULT || !disableCache) &&
51
- retrieval !== RETRIEVAL.NO_CACHE_NO_AWAIT;
52
+ const hasBody = body !== undefined;
53
+ const shouldCache = (retrieval !== RETRIEVAL.DEFAULT || (config.disableCache === undefined ? !hasBody : !disableCache)) &&
54
+ ![RETRIEVAL.NO_CACHE_NO_AWAIT, RETRIEVAL.NO_CACHE_AWAIT].includes(retrieval);
52
55
  const uglified = !!(!isBaseUrl && uglify);
53
56
 
54
57
  const rawHeader = Object.fromEntries(
55
58
  [...new Headers(headers).entries()]
56
59
  );
57
60
 
58
- if ('mtoken' in rawHeader)
59
- throw '"mtoken" in header is a reserved prop';
60
-
61
- if ('uglified' in rawHeader)
62
- throw '"uglified" in header is a reserved prop';
63
-
64
- // if (isBaseUrl && !rawApproach)
65
- // throw `please set { rawApproach: true } if you're trying to access different endpoint at "${input}"`;
61
+ ['mtoken', 'uglified'].forEach(e => {
62
+ if ([e] in rawHeader)
63
+ throw `"${e}" in header is a reserved prop`;
64
+ });
66
65
 
67
66
  if (body !== undefined) {
68
67
  if (
@@ -80,6 +79,7 @@ export const mfetch = async (input = '', init, config) => {
80
79
  input
81
80
  ]).toString('base64')
82
81
  );
82
+ const processReqId = `${reqId}_${disableCache}_${retrieval}`;
83
83
 
84
84
  let retries = 0, hasFinalize;
85
85
 
@@ -93,44 +93,38 @@ export const mfetch = async (input = '', init, config) => {
93
93
  hasFinalize = true;
94
94
 
95
95
  if (enableMinimizer) {
96
- (Scoped.PendingFetchCollective.pendingResolution[reqId] || []).forEach(e => {
96
+ const resolutionList = (Scoped.PendingFetchCollective[processReqId] || []).slice(0);
97
+
98
+ if (Scoped.PendingFetchCollective[processReqId])
99
+ delete Scoped.PendingFetchCollective[processReqId];
100
+
101
+ resolutionList.forEach(e => {
97
102
  e(a, b);
98
103
  });
99
- if (Scoped.PendingFetchCollective.pendingResolution[reqId])
100
- delete Scoped.PendingFetchCollective.pendingResolution[reqId];
101
-
102
- if (Scoped.PendingFetchCollective.pendingProcess[reqId])
103
- delete Scoped.PendingFetchCollective.pendingProcess[reqId];
104
104
  }
105
105
  };
106
106
 
107
107
  await awaitStore();
108
- const reqData = CacheStore.FetchedStore[projectUrl]?.[reqId];
109
- const resolveCache = () => {
110
- finalize({
111
- ...buildFetchData(reqData),
112
- fromCache: true
113
- });
108
+ const resolveCache = (reqData) => {
109
+ finalize(buildFetchData(reqData), { fromCache: true });
114
110
  };
115
111
 
116
112
  try {
117
113
  if (retryProcess === 1) {
118
114
  if (enableMinimizer) {
119
- if (Scoped.PendingFetchCollective.pendingProcess[reqId]) {
120
- if (!Scoped.PendingFetchCollective.pendingResolution[reqId])
121
- Scoped.PendingFetchCollective.pendingResolution[reqId] = [];
122
-
123
- Scoped.PendingFetchCollective.pendingResolution[reqId].push((a, b) => {
115
+ if (Scoped.PendingFetchCollective[processReqId]) {
116
+ Scoped.PendingFetchCollective[processReqId].push((a, b) => {
124
117
  if (a) resolve(cloneDeep(a.result));
125
118
  else reject(cloneDeep(b));
126
119
  });
127
120
  return;
128
121
  }
129
- Scoped.PendingFetchCollective.pendingProcess[reqId] = true;
122
+ Scoped.PendingFetchCollective[processReqId] = [];
130
123
  }
131
124
 
125
+ const reqData = await getFetchResources(projectUrl, reqId);
132
126
  if (retrieval.startsWith('sticky') && reqData) {
133
- resolveCache();
127
+ resolveCache(reqData);
134
128
  if (retrieval !== RETRIEVAL.STICKY_RELOAD) return;
135
129
  }
136
130
  }
@@ -140,25 +134,26 @@ export const mfetch = async (input = '', init, config) => {
140
134
 
141
135
  const mtoken = Scoped.AuthJWTToken[projectUrl];
142
136
  const initType = rawHeader['content-type'];
137
+ const encodeBody = initType === undefined && hasBody && !isBaseUrl;
143
138
 
144
139
  const [reqBuilder, [privateKey]] = uglified ? await serializeE2E(body, mtoken, serverE2E_PublicKey) : [null, []];
145
140
 
146
- const f = await fetch(isBaseUrl ? input : `${projectUrl}/${normalizeRoute(input)}`, {
147
- ...isBaseUrl ? {} : { method: 'POST' },
141
+ const f = await fetch(isLink ? input : `${projectUrl}/${normalizeRoute(input)}`, {
142
+ ...(!isBaseUrl || hasBody) ? { method: 'POST' } : {},
148
143
  ...init,
149
- ...uglified ? { body: reqBuilder } : {},
150
- cache: 'no-cache',
144
+ ...uglified ? { body: reqBuilder } : encodeBody ? { body: serialize(body) } : {},
145
+ // cache: 'no-cache',
151
146
  headers: {
152
147
  ...extraHeaders,
153
- ...isBaseUrl ? {} : { 'content-type': 'application/json' },
154
148
  ...rawHeader,
155
149
  ...uglified ? {
156
150
  uglified,
157
151
  'content-type': 'request/buffer',
158
152
  ...initType ? { 'init-content-type': initType } : {}
159
- } : {},
160
- ...(disableAuth || !mtoken || uglified || isBaseUrl) ? {} : { mtoken },
161
- ...isBaseUrl ? {} : { authorization: `Bearer ${accessKey}` }
153
+ } : encodeBody
154
+ ? { 'content-type': 'request/buffer', 'entity-encoded': '1' }
155
+ : {},
156
+ ...(disableAuth || !mtoken || uglified || isBaseUrl) ? {} : { mtoken }
162
157
  }
163
158
  });
164
159
  const { ok, type, status, statusText, redirected, url, headers, size } = f;
@@ -184,46 +179,42 @@ export const mfetch = async (input = '', init, config) => {
184
179
  )
185
180
  };
186
181
 
187
- if (shouldCache) {
188
- if (!CacheStore.FetchedStore[projectUrl])
189
- CacheStore.FetchedStore[projectUrl] = {};
190
- CacheStore.FetchedStore[projectUrl][reqId] = cloneDeep(resObj);
191
- updateCacheStore();
192
- }
182
+ if (shouldCache) insertFetchResources(projectUrl, reqId, resObj);
193
183
 
194
184
  finalize(buildFetchData(resObj));
195
185
  } catch (e) {
186
+ let thisRecord;
187
+
188
+ const getThisRecord = async () => thisRecord ? thisRecord[0]
189
+ : (thisRecord = [await getFetchResources(projectUrl, reqId)])[0];
190
+
196
191
  if (e?.simpleError) {
197
192
  finalize(undefined, e.simpleError);
198
193
  } else if (
199
- (retrieval === RETRIEVAL.CACHE_NO_AWAIT && !reqData) ||
194
+ (retrieval === RETRIEVAL.CACHE_NO_AWAIT && !(await getThisRecord())) ||
200
195
  retrieval === RETRIEVAL.STICKY_NO_AWAIT ||
201
196
  retrieval === RETRIEVAL.NO_CACHE_NO_AWAIT
202
197
  ) {
203
198
  finalize(undefined, simplifyCaughtError(e).simpleError);
204
199
  } else if (
205
200
  shouldCache &&
206
- (retrieval === RETRIEVAL.DEFAULT || retrieval === RETRIEVAL.CACHE_NO_AWAIT) &&
207
- reqData
201
+ [
202
+ RETRIEVAL.DEFAULT,
203
+ RETRIEVAL.CACHE_NO_AWAIT,
204
+ RETRIEVAL.CACHE_AWAIT
205
+ ].includes(retrieval) &&
206
+ await getThisRecord()
208
207
  ) {
209
- resolveCache();
210
- } else if (retries >= maxRetries) {
208
+ resolveCache(await getThisRecord());
209
+ } else if (retries > maxRetries) {
211
210
  finalize(undefined, simplifyCaughtError(e).simpleError);
212
211
  } else {
213
212
  const listener = listenReachableServer(async online => {
214
213
  if (online) {
215
214
  listener();
216
215
  callFetch().then(
217
- e => {
218
- if (retryProcess === 1) {
219
- finalize(e);
220
- } else resolve(e);
221
- },
222
- e => {
223
- if (retryProcess === 1) {
224
- finalize(undefined, e);
225
- } else reject(e);
226
- }
216
+ e => finalize(e),
217
+ e => finalize(undefined, e)
227
218
  );
228
219
  }
229
220
  }, projectUrl);
@@ -231,5 +222,5 @@ export const mfetch = async (input = '', init, config) => {
231
222
  }
232
223
  });
233
224
 
234
- return await callFetch();
225
+ return (await callFetch());
235
226
  };
@@ -1,8 +1,8 @@
1
1
  import EngineApi from "../../helpers/engine_api";
2
- import { encodeBinary, prefixStoragePath } from "../../helpers/peripherals";
2
+ import { deserializeE2E, prefixStoragePath } from "../../helpers/peripherals";
3
3
  import { Scoped } from "../../helpers/variables";
4
4
  import { DeviceEventEmitter, NativeEventEmitter, NativeModules, Platform } from 'react-native';
5
- import { awaitReachableServer, buildFetchInterface } from "../../helpers/utils";
5
+ import { awaitReachableServer, buildFetchInterface, buildFetchResult } from "../../helpers/utils";
6
6
  import { awaitRefreshToken } from "../auth/accessor";
7
7
  import { simplifyError } from "simplify-error";
8
8
 
@@ -31,7 +31,7 @@ export class MTStorage {
31
31
  const { awaitServer } = options || {};
32
32
  let hasFinished, isPaused, hasCancelled;
33
33
 
34
- const { projectUrl, accessKey, extraHeaders } = this.builder;
34
+ const { projectUrl, extraHeaders } = this.builder;
35
35
 
36
36
  if (destination && (typeof destination !== 'string' || !destination.trim())) {
37
37
  onComplete?.({ error: 'destination_invalid', message: 'destination must be a non-empty string' });
@@ -98,7 +98,6 @@ export class MTStorage {
98
98
  } : {},
99
99
  processID,
100
100
  urlName: link.split('/').pop(),
101
- authorization: `Bearer ${encodeBinary(accessKey)}`,
102
101
  extraHeaders: extraHeaders || {},
103
102
  });
104
103
  }
@@ -136,7 +135,7 @@ export class MTStorage {
136
135
 
137
136
  file = isAsset ? file.trim() : prefixStoragePath(file.trim());
138
137
 
139
- const { projectUrl, accessKey, uglify, extraHeaders } = this.builder;
138
+ const { projectUrl, uglify, extraHeaders } = this.builder;
140
139
  const processID = `${++Scoped.StorageProcessID}`;
141
140
 
142
141
  const init = async () => {
@@ -171,7 +170,6 @@ export class MTStorage {
171
170
  createHash: createHash ? 'yes' : 'no',
172
171
  destination,
173
172
  processID,
174
- authorization: `Bearer ${encodeBinary(accessKey)}`,
175
173
  extraHeaders: extraHeaders || {}
176
174
  });
177
175
  }
@@ -192,16 +190,25 @@ export class MTStorage {
192
190
  deleteFolder = (path) => deleteContent(this.builder, path, true);
193
191
  }
194
192
 
193
+ const { _deleteFile, _deleteFolder } = EngineApi;
194
+
195
195
  const deleteContent = async (builder, path, isFolder) => {
196
- const { projectUrl, accessKey, uglify } = builder;
196
+ const { projectUrl, uglify, extraHeaders, serverE2E_PublicKey } = builder;
197
197
 
198
198
  try {
199
- const r = await (await fetch(
200
- EngineApi[isFolder ? '_deleteFolder' : '_deleteFile'](projectUrl, uglify),
201
- await buildFetchInterface({ path }, accessKey, Scoped.AuthJWTToken[projectUrl], 'DELETE')
202
- )).json();
203
- if (r.simpleError) throw r;
204
- if (r.status !== 'success') throw 'operation not successful';
199
+ const [reqBuilder, [privateKey]] = await buildFetchInterface({
200
+ method: 'DELETE',
201
+ authToken: Scoped.AuthJWTToken[projectUrl],
202
+ body: { path },
203
+ extraHeaders,
204
+ serverE2E_PublicKey,
205
+ uglify
206
+ });
207
+
208
+ const data = await buildFetchResult(await fetch((isFolder ? _deleteFolder : _deleteFile)(projectUrl, uglify), reqBuilder), uglify);
209
+ const result = uglify ? await deserializeE2E(data, serverE2E_PublicKey, privateKey) : data;
210
+
211
+ if (result.status !== 'success') throw 'operation not successful';
205
212
  } catch (e) {
206
213
  if (e?.simpleError) throw e.simpleError;
207
214
  throw simplifyError('unexpected_error', `${e}`).simpleError;