react-native-mosquito-transport 0.0.35 → 0.0.36

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.35",
3
+ "version": "0.0.36",
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",
@@ -1,6 +1,8 @@
1
+ import { deserialize, serialize } from "entity-serializer";
1
2
  import { Scoped } from "./variables";
2
3
  import { Platform } from "react-native";
3
4
  import { Dirs, FileSystem } from "react-native-file-access";
5
+ import { Buffer } from "buffer";
4
6
 
5
7
  const PARENT_FOLDER = `${Platform.OS === 'android' ? Dirs.DocumentDir.split('/').slice(0, -1).join('/') : Dirs.MainBundleDir}/mosquito_base`;
6
8
 
@@ -48,7 +50,7 @@ export const getSystem = (builder) => {
48
50
  const path = conjoin(table, primary_key);
49
51
  await FileSystem.mkdir(path).catch(() => null);
50
52
  await Promise.all(Object.entries(value).map(([k, v]) =>
51
- FileSystem.writeFile(joinPath(path, k), JSON.stringify(v), 'utf8')
53
+ FileSystem.writeFile(joinPath(path, k), serialize(v).toString('base64'), 'base64')
52
54
  ));
53
55
  },
54
56
  delete: (table, primary_key) => FileSystem.unlink(conjoin(table, primary_key)),
@@ -56,7 +58,7 @@ export const getSystem = (builder) => {
56
58
  const path = conjoin(table, primary_key);
57
59
 
58
60
  const value_map = await Promise.all(extractions.map(async node =>
59
- [node, JSON.parse(await FileSystem.readFile(joinPath(path, node), 'utf8'))]
61
+ [node, deserialize(Buffer.from(await FileSystem.readFile(joinPath(path, node), 'base64'), 'base64'))]
60
62
  ));
61
63
  return Object.fromEntries(value_map);
62
64
  },
@@ -245,7 +245,7 @@ export const purgeRedundantRecords = async (data, builder) => {
245
245
  }
246
246
  }
247
247
 
248
- const breakDbMap = (obj, callback) =>
248
+ export const breakDbMap = (obj = {}, callback) =>
249
249
  Object.entries(obj).forEach(([projectUrl, dbUrlObj]) => {
250
250
  Object.entries(dbUrlObj).forEach(([dbUrl, dbNameObj]) => {
251
251
  Object.entries(dbNameObj).forEach(([dbName, pathObj]) => {
@@ -1,15 +1,31 @@
1
1
  import { ServerReachableListener, StoreReadyListener } from "./listeners";
2
2
  import { CacheStore, Scoped } from "./variables";
3
3
  import { serializeE2E } from "./peripherals";
4
- import { deserializeBSON, serializeToBase64 } from "../products/database/bson";
5
- import { deserialize } from "entity-serializer";
6
- import { purgeRedundantRecords } from "./purger";
4
+ import { DatastoreParser } from "../products/database/bson";
5
+ import { deserialize, serialize } from "entity-serializer";
6
+ import { breakDbMap, purgeRedundantRecords } from "./purger";
7
7
  import { FS_PATH, getSystem } from "./fs_manager";
8
+ import cloneDeep from "lodash/cloneDeep";
8
9
 
9
10
  const { FILE_NAME, TABLE_NAME } = FS_PATH;
10
11
 
11
12
  const CacheKeys = Object.keys(CacheStore);
12
13
 
14
+ const prefillDatastore = (obj, caller) => {
15
+ obj = cloneDeep(obj);
16
+ breakDbMap(obj, (_projectUrl, _dbUrl, _dbName, _path, value) => {
17
+ Object.entries(value.instance).forEach(([access_id, obj]) => {
18
+ value.instance[access_id] = caller(obj);
19
+ });
20
+ Object.entries(value.episode).forEach(([_access_id, limitObj]) => {
21
+ Object.entries(limitObj).forEach(([limit, obj]) => {
22
+ limitObj[limit] = caller(obj);
23
+ });
24
+ });
25
+ });
26
+ return obj;
27
+ };
28
+
13
29
  export const updateCacheStore = async (node) => {
14
30
  const { io, promoteCache } = Scoped.ReleaseCacheData;
15
31
 
@@ -22,14 +38,24 @@ export const updateCacheStore = async (node) => {
22
38
  ...restStore
23
39
  } = CacheStore;
24
40
 
41
+ const minimizePendingWrite = () => {
42
+ const obj = cloneDeep(PendingWrites);
43
+ Object.values(obj).forEach(e => {
44
+ Object.values(e).forEach(b => {
45
+ if ('editions' in b) delete b.editions;
46
+ });
47
+ });
48
+ return obj;
49
+ }
50
+
25
51
  if (io) {
26
52
  const txt = JSON.stringify({
27
53
  AuthStore,
28
54
  EmulatedAuth,
29
55
  PendingAuthPurge,
30
56
  ...promoteCache ? {
31
- DatabaseStore: serializeToBase64(DatabaseStore),
32
- PendingWrites: serializeToBase64(PendingWrites)
57
+ DatabaseStore: prefillDatastore(DatabaseStore, DatastoreParser.encode),
58
+ PendingWrites: minimizePendingWrite()
33
59
  } : {},
34
60
  ...promoteCache ? restStore : {}
35
61
  });
@@ -43,7 +69,7 @@ export const updateCacheStore = async (node) => {
43
69
  if (!updationKey.length) return;
44
70
  await Promise.all(
45
71
  updationKey
46
- .map(v => [v, v === 'PendingWrites' ? serializeToBase64(CacheStore[v]) : CacheStore[v]])
72
+ .map(v => [v, v === 'PendingWrites' ? minimizePendingWrite() : CacheStore[v]])
47
73
  .map(([ref, value]) =>
48
74
  getSystem(FILE_NAME).set(TABLE_NAME, ref, { value })
49
75
  )
@@ -61,27 +87,27 @@ export const releaseCacheStore = async (builder) => {
61
87
  try {
62
88
  if (io) {
63
89
  data = JSON.parse((await io.input()) || '{}');
64
- } else {
65
- try {
66
- const query = await getSystem(FILE_NAME).list(TABLE_NAME, ['value']).catch(() => []);
67
- data = Object.fromEntries(
68
- query.map(([ref, { value }]) =>
69
- [ref, value]
70
- )
90
+
91
+ if (data.DatabaseStore)
92
+ data.DatabaseStore = prefillDatastore(
93
+ data.DatabaseStore,
94
+ r => DatastoreParser.decode(r, false)
71
95
  );
72
- } catch (error) {
73
- console.error('initializeCache data release err:', error);
74
- }
96
+ } else {
97
+ const query = await getSystem(FILE_NAME).list(TABLE_NAME, ['value']).catch(() => []);
98
+ data = Object.fromEntries(
99
+ query.map(([ref, { value }]) =>
100
+ [ref, value]
101
+ )
102
+ );
75
103
  }
76
104
  await purgeRedundantRecords(data, builder);
77
105
  } catch (e) {
78
- console.error('initializeCache data err:', e);
106
+ console.error('releaseCacheStore data err:', e);
79
107
  }
80
108
 
81
109
  Object.entries(data).forEach(([k, v]) => {
82
- if (['DatabaseStore', 'PendingWrites'].includes(k)) {
83
- CacheStore[k] = deserializeBSON(v);
84
- } else CacheStore[k] = v;
110
+ CacheStore[k] = v;
85
111
  });
86
112
  Object.entries(CacheStore.AuthStore).forEach(([key, value]) => {
87
113
  Scoped.AuthJWTToken[key] = value?.token;
@@ -8,7 +8,7 @@ import { BSONRegExp, ObjectId, Timestamp } from "../../vendor/bson";
8
8
  import { niceGuard, Validator } from "guard-object";
9
9
  import { TIMESTAMP } from "../..";
10
10
  import { docSize, incrementDatabaseSize } from "./counter";
11
- import { deserializeBSON, serializeToBase64 } from "./bson";
11
+ import { DatastoreParser, serializeToBase64 } from "./bson";
12
12
  import { FS_PATH, getSystem, useFS } from "../../helpers/fs_manager";
13
13
  import { grab, poke, unpoke } from "poke-object";
14
14
 
@@ -100,14 +100,13 @@ export const insertRecord = async (builder, config, accessIdWithoutLimit, value,
100
100
  const editionSizeOffset = thisSize - (instanceData?.size || 0);
101
101
  const resultSizeOffset = isEpisode ? thisSize - (resultData?.size || 0) : 0;
102
102
 
103
- const newData = serializeToBase64({
103
+ const newData = DatastoreParser.encode({
104
104
  command,
105
105
  config,
106
106
  latest_limiter: limit,
107
- size: thisSize,
108
107
  data: value ? Array.isArray(value) ? value : [value] : []
109
108
  });
110
- const newResultData = isEpisode && serializeToBase64({
109
+ const newResultData = isEpisode && DatastoreParser.encode({
111
110
  data: value,
112
111
  size: thisSize
113
112
  });
@@ -195,7 +194,7 @@ export const getRecord = async (builder, accessIdWithoutLimit, episode = 0) => {
195
194
  isEpisode ? fs.find(LIMITER_RESULT(path), resultAccessId, ['value']) :
196
195
  fs.find(LIMITER_DATA(path), accessIdWithoutLimit, ['value'])
197
196
  ).catch(() => null);
198
- const thisData = qData && deserializeBSON(qData.value, true);
197
+ const thisData = qData && DatastoreParser.decode(qData.value);
199
198
 
200
199
  if (!thisData) return null;
201
200
 
@@ -283,7 +282,7 @@ const arrangeCommands = (c, removeLimit) => {
283
282
  if (c.sort) c.direction = [-1, 'desc', 'descending'].includes(c.direction) ? 'desc' : 'asc';
284
283
  if (c.find) c.find = sortFind(c.find);
285
284
  if (c.findOne) c.findOne = sortFind(c.findOne);
286
- if (removeLimit && 'limit' in c) delete c.limit;
285
+ if (removeLimit && ('limit' in c)) delete c.limit;
287
286
  return sortObject(c);
288
287
  };
289
288
 
@@ -421,18 +420,18 @@ export const addPendingWrites = async (builder, writeId, result) => {
421
420
  await Promise.all(colListing.map(async ([access_id]) =>
422
421
  useFS(builder, access_id, 'database')(async fs => {
423
422
  const data = await fs.find(LIMITER_DATA(path), access_id, ['value'])
424
- .then(r => deserializeBSON(r.value, true));
423
+ .then(r => DatastoreParser.decode(r.value));
425
424
 
426
425
  await MutateDataInstance([access_id, data], path =>
427
426
  pathFinder[path] || (
428
427
  pathFinder[path] = fs.list(LIMITER_DATA(path), ['value'])
429
- .then(v => v.map(d => deserializeBSON(d[1].value, true).data).flat())
428
+ .then(v => v.map(d => DatastoreParser.decode(d[1].value).data).flat())
430
429
  .catch(() => [])
431
430
  )
432
431
  );
433
432
  await fs.set(LIMITER_DATA(path), access_id, {
434
433
  touched: Date.now(),
435
- value: serializeToBase64(data),
434
+ value: DatastoreParser.encode(data),
436
435
  size: data.size
437
436
  });
438
437
  })
@@ -654,7 +653,7 @@ export const addPendingWrites = async (builder, writeId, result) => {
654
653
  });
655
654
  const pureBuilder = {};
656
655
 
657
- ['path', 'dbUrl', 'dbName', 'find', 'extraHeaders'].forEach(v => {
656
+ ['path', 'dbUrl', 'dbName', 'find', 'extraHeaders', 'maxRetries'].forEach(v => {
658
657
  if (builder[v] !== undefined) pureBuilder[v] = builder[v];
659
658
  });
660
659
  pureBuilder.find = serializeToBase64({ _: pureBuilder.find });
@@ -711,12 +710,12 @@ export const removePendingWrite = async (builder, writeId, revert) => {
711
710
  } else {
712
711
  await useFS(builder, access_id, 'database')(async fs => {
713
712
  const colObj = await fs.find(LIMITER_DATA(path), access_id, ['value'])
714
- .then(v => deserializeBSON(v.value, true))
713
+ .then(v => DatastoreParser.decode(v.value))
715
714
  .catch(() => null);
716
715
  if (!colObj) return;
717
716
  RevertMutation(colObj);
718
717
  await fs.set(LIMITER_DATA(path), access_id, {
719
- value: serializeToBase64(colObj),
718
+ value: DatastoreParser.encode(colObj),
720
719
  touched: Date.now(),
721
720
  size: colObj.size
722
721
  });
@@ -1,3 +1,4 @@
1
+ import { cloneDeep } from "lodash";
1
2
  import { deserialize, serialize } from "../../vendor/bson";
2
3
  import { Buffer } from "buffer";
3
4
 
@@ -13,4 +14,45 @@ export const deserializeBSON = (data, cast) => {
13
14
  });
14
15
  };
15
16
 
16
- export const serializeToBase64 = doc => Buffer.from(serialize(doc)).toString('base64');
17
+ export const serializeToBase64 = doc => Buffer.from(serialize(doc)).toString('base64');
18
+
19
+ export const DatastoreParser = {
20
+ encode: (obj) => {
21
+ obj = cloneDeep(obj);
22
+ const { command, config } = obj;
23
+
24
+ const serializeQuery = (e) =>
25
+ ['find', 'findOne'].forEach(n => {
26
+ if (e?.[n]) e[n] = serializeToBase64({ _: e[n] });
27
+ });
28
+
29
+ if (command) serializeQuery(command);
30
+ if (config) {
31
+ if (config.extraction)
32
+ (Array.isArray(config.extraction) ? config.extraction : [config.extraction]).forEach(e => {
33
+ serializeQuery(e);
34
+ });
35
+ }
36
+ if (obj.data) obj.data = serializeToBase64({ _: obj.data });
37
+ return obj;
38
+ },
39
+ decode: (obj, cast = true) => {
40
+ obj = cloneDeep(obj);
41
+ const { command, config } = obj;
42
+
43
+ const serializeQuery = (e) =>
44
+ ['find', 'findOne'].forEach(n => {
45
+ if (e?.[n]) e[n] = deserializeBSON(e[n], cast)._;
46
+ });
47
+
48
+ if (command) serializeQuery(command);
49
+ if (config) {
50
+ if (config.extraction)
51
+ (Array.isArray(config.extraction) ? config.extraction : [config.extraction]).forEach(e => {
52
+ serializeQuery(e);
53
+ });
54
+ }
55
+ if (obj.data) obj.data = deserializeBSON(obj.data, cast)._;
56
+ return obj;
57
+ }
58
+ };
@@ -395,6 +395,7 @@ const countCollection = async (builder, config) => {
395
395
  const b4Data = await getCountQuery(builder, accessId).catch(() => null);
396
396
 
397
397
  if (e?.simpleError) {
398
+ e.simpleError.ack = true;
398
399
  finalize(undefined, e.simpleError);
399
400
  } else if (!disableCache && Validator.NUMBER(b4Data)) {
400
401
  finalize(b4Data);
@@ -552,6 +553,7 @@ const findObject = async (builder, config) => {
552
553
  (thisRecord = [await getRecordData()])[0];
553
554
 
554
555
  if (e?.simpleError) {
556
+ e.simpleError.ack = true;
555
557
  finalize(undefined, e?.simpleError);
556
558
  } else if (
557
559
  (retrieval === RETRIEVAL.CACHE_NO_AWAIT && !(await getThisRecord())) ||
@@ -689,7 +691,8 @@ const commitData = async (builder, value, type, config) => {
689
691
  } catch (e) {
690
692
  if (e?.simpleError) {
691
693
  console.error(`${type} error (${path}), ${e.simpleError?.message}`);
692
- finalize(undefined, e?.simpleError, { removeCache: true, revertCache: true });
694
+ e.simpleError.ack = true;
695
+ finalize(undefined, e.simpleError, { removeCache: true, revertCache: true });
693
696
  } else if (delivery === DELIVERY.NO_CACHE_NO_AWAIT) {
694
697
  finalize(undefined, simplifyCaughtError(e).simpleError);
695
698
  } else if (retries > maxRetries) {
@@ -738,9 +741,9 @@ export const trySendPendingWrite = (projectUrl) => {
738
741
 
739
742
  delete CacheStore.PendingWrites[projectUrl][writeId];
740
743
  ++resolveCounts;
741
- } catch (_) {
744
+ } catch (err) {
742
745
  const { maxRetries } = builder;
743
- if (!maxRetries || attempts >= maxRetries) {
746
+ if (err?.ack || !maxRetries || attempts >= maxRetries) {
744
747
  delete CacheStore.PendingWrites[projectUrl][writeId];
745
748
  ++resolveCounts;
746
749
  } else if (CacheStore.PendingWrites[projectUrl]?.[writeId]) {