mosquito-transport-js 0.2.8 → 0.2.9

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/.jshintignore ADDED
@@ -0,0 +1,2 @@
1
+ node_modules/
2
+ dist/
package/.jshintrc ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "undef": true, // Warns on variables used before declaration
3
+ "esversion": 12,
4
+ "globals": {
5
+ "process": true,
6
+ "clearTimeout": true,
7
+ "setTimeout": true,
8
+ "console": true,
9
+ "Buffer": true,
10
+ "clearInterval": true,
11
+ "setInterval": true,
12
+ "AbortController": true,
13
+ "URLSearchParams": true
14
+ }
15
+ }
package/TODO CHANGED
@@ -3,4 +3,7 @@
3
3
  - reauthenticate
4
4
  - change `Object` in d.ts to [key: string]: any
5
5
  - add `getServerTimeOffset` method
6
- - change null to undefined in `value`
6
+ - change null to undefined in `value`
7
+ - `provide functionality to add extra header to MT instance (all outgoing request)`
8
+ - borrowToken
9
+ - `add sqlite`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mosquito-transport-js",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Javascript web sdk for mosquito-transport (https://github.com/deflexable/mosquito-transport)",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -28,18 +28,18 @@
28
28
  },
29
29
  "homepage": "https://github.com/brainbehindx/mosquito-transport-js#readme",
30
30
  "dependencies": {
31
- "@types/crypto-js": "^4.2.1",
32
- "@types/lodash": "^4.14.194",
31
+ "@turf/turf": "^7.1.0",
32
+ "bson": "^6.8.0",
33
33
  "buffer": "^6.0.3",
34
34
  "crypto-js": "^4.2.0",
35
- "fast-json-stable-stringify": "^2.1.0",
36
- "guard-object": "^1.0.9",
35
+ "guard-object": "^1.1.0",
37
36
  "json-buffer": "^3.0.1",
37
+ "lodash.clonedeep": "^4.5.0",
38
38
  "lodash.get": "^4.4.2",
39
- "lodash.isequal": "^4.5.0",
40
39
  "lodash.set": "^4.3.2",
41
40
  "lodash.unset": "^4.5.2",
42
41
  "set-large-timeout": "^1.0.1",
42
+ "simplify-error": "^1.0.1",
43
43
  "socket.io-client": "^4.6.2",
44
44
  "subscription-listener": "^1.1.2",
45
45
  "tweetnacl": "^1.0.3"
@@ -0,0 +1,53 @@
1
+ import { initTokenRefresher, triggerAuthToken } from "../products/auth/accessor";
2
+ import { notifyDatabaseNodeChanges, revertChanges, syncCache } from "../products/database/accessor";
3
+ import { deserializeBSON } from "../products/database/bson";
4
+ import { TokenRefreshListener } from "./listeners";
5
+ import { awaitStore } from "./utils";
6
+ import { CacheStore, Scoped } from "./variables";
7
+
8
+ const InstanceID = `${Math.random()}`;
9
+ const broadcaster = new BroadcastChannel('MT_BROADCASTER');
10
+
11
+ broadcaster.onmessage = async (e) => {
12
+ const { kind, context, data } = JSON.parse(e.data);
13
+ if (context === InstanceID) return;
14
+ await awaitStore();
15
+
16
+ if (kind === 'auth') {
17
+ const { projectUrl, authData } = data;
18
+ CacheStore.AuthStore[projectUrl] = authData;
19
+ Scoped.AuthJWTToken[projectUrl] = authData?.token;
20
+ TokenRefreshListener.dispatch(projectUrl);
21
+ triggerAuthToken(projectUrl);
22
+ initTokenRefresher(Scoped.InitializedProject[projectUrl]);
23
+ } else if (kind === 'database-sync') {
24
+ // only if cache protocol is in-memory
25
+ const { builder, result, writeId } = data;
26
+ const { editions, pathChanges } = syncCache(builder, deserializeBSON(result)._);
27
+ Scoped.broadcastedWrites[writeId] = { editions, builder };
28
+ notifyDatabaseNodeChanges(builder, pathChanges);
29
+ } else if (kind === 'database-revert') {
30
+ // only if cache protocol is in-memory
31
+ const { writeId, revert } = data;
32
+ if (!Scoped.broadcastedWrites[writeId]) return;
33
+
34
+ const { editions, builder } = Scoped.broadcastedWrites[writeId];
35
+ if (revert) {
36
+ const pathChanges = revertChanges(builder, editions);
37
+ notifyDatabaseNodeChanges(builder, pathChanges);
38
+ }
39
+ delete Scoped.broadcastedWrites[writeId];
40
+ }
41
+ };
42
+
43
+ const sendMessage = (event, data) => {
44
+ broadcaster.postMessage(
45
+ JSON.stringify({
46
+ kind: event,
47
+ context: InstanceID,
48
+ data
49
+ })
50
+ );
51
+ };
52
+
53
+ export default sendMessage;
@@ -0,0 +1,39 @@
1
+ import { encodeBinary } from './peripherals';
2
+
3
+ const EngineApiBase = (baseApi, ugly, path) => {
4
+ const url = new URL(baseApi);
5
+ if (ugly) {
6
+ url.pathname = `/e2e/${encodeBinary(path)}`;
7
+ } else url.pathname = path;
8
+ return url.href;
9
+ };
10
+
11
+ const apis = {
12
+ _readDocument: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_readDocument'),
13
+ _queryCollection: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_queryCollection'),
14
+ _documentCount: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_documentCount'),
15
+ _writeDocument: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_writeDocument'),
16
+ _writeMapDocument: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_writeMapDocument'),
17
+ _customSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_customSignin'),
18
+ _customSignup: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_customSignup'),
19
+ _googleSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_googleSignin'),
20
+ _appleSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_appleSignin'),
21
+ _facebookSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_facebookSignin'),
22
+ _twitterSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_twitterSignin'),
23
+ _githubSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_githubSignin'),
24
+ _signOut: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_signOut'),
25
+ _refreshAuthToken: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_refreshAuthToken'),
26
+ _uploadFile: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_uploadFile'),
27
+ _deleteFile: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_deleteFile'),
28
+ _deleteFolder: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_deleteFolder'),
29
+ staticStorage: (baseApi) => `${baseApi}/storage`,
30
+ _areYouOk: (baseApi) => `${baseApi}/_areYouOk`,
31
+ // static path
32
+ _listenCollection: (ugly) => ugly ? encodeBinary(apis._listenCollection()) : '_listenCollection',
33
+ _listenDocument: (ugly) => ugly ? encodeBinary(apis._listenDocument()) : '_listenDocument',
34
+ _startDisconnectWriteTask: (ugly) => ugly ? encodeBinary(apis._startDisconnectWriteTask()) : '_startDisconnectWriteTask',
35
+ _cancelDisconnectWriteTask: (ugly) => ugly ? encodeBinary(apis._cancelDisconnectWriteTask()) : '_cancelDisconnectWriteTask',
36
+ _listenUserVerification: (ugly) => ugly ? encodeBinary(apis._listenUserVerification()) : '_listenUserVerification'
37
+ };
38
+
39
+ export default { ...apis };
@@ -3,123 +3,33 @@ import { ServerReachableListener } from "./listeners";
3
3
  import aes_pkg from 'crypto-js/aes.js';
4
4
  import Utf8Encoder from 'crypto-js/enc-utf8.js';
5
5
  import naclPkg from 'tweetnacl';
6
+ import getLodash from "lodash.get";
6
7
 
7
8
  const { encrypt, decrypt } = aes_pkg;
8
9
  const { box, randomBytes } = naclPkg;
9
10
 
10
- export const simplifyError = (error, message) => ({
11
- simpleError: { error, message }
12
- });
13
-
14
- export const simplifyCaughtError = (e) => e?.simpleError ? e : simplifyError('unexpected_error', `${e}`);
15
-
16
- export const everyEntrie = (obj, callback) => {
17
- if (typeof obj !== 'object' || Array.isArray(obj)) return;
18
- oEntries(obj).forEach(e => {
19
- callback?.(e);
20
- });
21
- }
22
-
23
- export const flatEntries = (obj) => oEntries(obj);
24
-
25
- export const flatRawEntries = () => oEntries(obj, false);
26
-
27
- export const oEntries = (obj, includeObj = true) => {
28
- let o = [];
29
-
30
- Object.entries(obj).forEach(e => {
31
- o.push(e);
32
- if (e[1] && typeof e[1] === 'object' && !Array.isArray(e[1])) {
33
- o = [...o, ...oEntries(e[1])];
34
- }
35
- });
36
-
37
- return o.filter(v => includeObj || typeof v[1] !== 'object' || Array.isArray(v[1]));
38
- }
39
-
40
- export const IS_RAW_OBJECT = (e) => e && typeof e === 'object' && !Array.isArray(e) && !(e instanceof Date);
41
-
42
- export const IS_WHOLE_NUMBER = (v) => typeof v === 'number' && !`${v}`.includes('.');
43
-
44
- export const IS_DECIMAL_NUMBER = (v) => typeof v === 'number' && `${v}`.includes('.');
45
-
46
- export const queryEntries = (obj, lastPath = '', exceptions = [], seperator = '.') => {
47
- let o = [];
48
- const isArraySeperator = Array.isArray(lastPath);
49
-
50
- Object.entries(obj).forEach(([key, value]) => {
51
- if (IS_RAW_OBJECT(value) && !exceptions.includes(key)) {
52
- o = [
53
- ...o,
54
- ...queryEntries(
55
- value,
56
- isArraySeperator ? [...lastPath, key] : `${lastPath}${key}${seperator}`,
57
- exceptions,
58
- seperator
59
- )
60
- ];
61
- } else o.push(isArraySeperator ? [[...lastPath, key], value] : [`${lastPath}${key}`, value]);
62
- });
63
-
64
- return o;
65
- }
66
-
67
- export const objToUniqueString = (obj) => {
68
- const keys = [],
69
- values = [];
70
-
71
- if (Array.isArray(obj)) {
72
- obj.forEach(e => {
73
- if (IS_RAW_OBJECT(e)) {
74
- queryEntries(e).map(([k, v]) => {
75
- keys.push(k);
76
- values.push(v);
77
- });
78
- } else keys.push(Array.isArray(e) ? JSON.stringify(e) : `${e}`);
79
- });
80
- } else if (!IS_RAW_OBJECT(obj))
81
- return `${obj}`;
82
- else
83
- queryEntries(obj).map(([k, v]) => {
84
- keys.push(k);
85
- values.push(v);
86
- });
87
-
88
- return [
89
- ...keys.sort(),
90
- ...values.map(v => `${Array.isArray(v) ? JSON.stringify(v) : v}`).sort()
91
- ].join(',');
92
- }
93
-
94
- export const cloneInstance = (v) => {
95
- if (v && typeof v === 'object') {
96
- return Array.isArray(v) ? [...v] : { ...v };
97
- }
98
- return v;
99
- }
100
-
101
11
  export const listenReachableServer = (callback, projectUrl) => {
102
12
  let lastValue;
103
13
  return ServerReachableListener.listenTo(projectUrl, t => {
104
14
  if (typeof t === 'boolean' && t !== lastValue) callback?.(t);
105
15
  }, true);
106
- }
16
+ };
107
17
 
108
18
  export const prefixStoragePath = (path, prefix = 'file:///') => {
109
- if (!path) return path;
19
+ let cleanedPath = path.replace(/^[^/]+:\/{1,3}/, '');
110
20
 
111
- if (!path.startsWith('/') && !path.includes(':')) return prefix + path;
21
+ // Continuously remove any remaining protocol patterns until none are left
22
+ while (/^[^/]+:\/{1,3}/.test(cleanedPath)) {
23
+ cleanedPath = cleanedPath.replace(/^[^/]+:\/{1,3}/, '');
24
+ }
112
25
 
113
- return prefix + path.split('/').filter((v, i) => i && v).join('/');
114
- }
26
+ // Remove any leading slashes after protocol removal
27
+ cleanedPath = cleanedPath.replace(/^\/+/, '');
115
28
 
116
- export const getUrlExtension = (url) => {
117
- const r = url.split(/[#?]/)[0].split(".").pop().trim();
118
- return r === url ? '' : r;
119
- }
29
+ return `${prefix}${cleanedPath}`;
30
+ };
120
31
 
121
32
  export const niceTry = (promise) => new Promise(async resolve => {
122
-
123
33
  try {
124
34
  const r = await promise();
125
35
  resolve(r);
@@ -143,21 +53,50 @@ export const shuffleArray = (n) => {
143
53
  }
144
54
 
145
55
  export function sortArrayByObjectKey(arr = [], key) {
146
- return arr.slice(0).sort(function (a, b) {
56
+ return arr.sort(function (a, b) {
147
57
  const left = getLodash(a, key),
148
58
  right = getLodash(b, key);
149
59
 
150
60
  return (left > right) ? 1 : (left < right) ? -1 : 0;
151
61
  });
152
- }
62
+ };
63
+
64
+ export async function niceHash(str) {
65
+ try {
66
+ // Convert the string to a Uint8Array
67
+ const encoder = new TextEncoder();
68
+ const data = encoder.encode(str);
69
+
70
+ // Use the Web Crypto API to compute the hash
71
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
72
+
73
+ // Convert the ArrayBuffer to a hex string for readability
74
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
75
+ const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
76
+
77
+ // Convert to base64
78
+ return Buffer.from(hashHex, 'hex').toString('base64');
79
+ } catch (_) {
80
+ return str;
81
+ }
82
+ };
83
+
84
+ export const sameInstance = (var1, var2) => {
85
+ try {
86
+ return var1.constructor === var2.constructor &&
87
+ Object.getPrototypeOf(var1) === Object.getPrototypeOf(var2)
88
+ } catch (_) {
89
+ return false;
90
+ }
91
+ };
153
92
 
154
93
  export const encryptString = (txt, password, iv) => {
155
94
  return encrypt(txt, `${password || ''}${iv || ''}`).toString();
156
- }
95
+ };
157
96
 
158
97
  export const decryptString = (txt, password, iv) => {
159
98
  return decrypt(txt, `${password || ''}${iv || ''}`).toString(Utf8Encoder);
160
- }
99
+ };
161
100
 
162
101
  export const serializeE2E = (data, auth_token, serverPublicKey) => {
163
102
  const pair = box.keyPair(),
@@ -179,7 +118,7 @@ export const serializeE2E = (data, auth_token, serverPublicKey) => {
179
118
  ).toString('base64')}`,
180
119
  [pair.secretKey, pair.publicKey]
181
120
  ];
182
- }
121
+ };
183
122
 
184
123
  export const deserializeE2E = (data, serverPublicKey, clientPrivateKey) => {
185
124
  const [binaryNonce, binaryData] = data.split('.'),
@@ -192,7 +131,7 @@ export const deserializeE2E = (data, serverPublicKey, clientPrivateKey) => {
192
131
 
193
132
  if (!baseArray) throw 'Decrypting e2e message failed';
194
133
  return JSON.parse(Buffer.from(baseArray).toString('utf8'))[0];
195
- }
134
+ };
196
135
 
197
136
  export const encodeBinary = (s) => Buffer.from(s, 'utf8').toString('base64');
198
137
  export const decodeBinary = (s) => Buffer.from(s, 'base64').toString('utf8');
@@ -2,19 +2,31 @@ import { ServerReachableListener, StoreReadyListener } from "./listeners";
2
2
  import { CACHE_PROTOCOL, CACHE_STORAGE_PATH, DEFAULT_CACHE_PASSWORD } from "./values";
3
3
  import { CacheStore, Scoped } from "./variables";
4
4
  import { decryptString, encryptString, serializeE2E } from "./peripherals";
5
+ import { deserializeBSON, serializeToBase64 } from "../products/database/bson";
6
+ import { trySendPendingWrite } from "../products/database";
5
7
 
6
- export const updateCacheStore = () => {
8
+ export const updateCacheStore = (timer = 300) => {
7
9
  try { window } catch (_) { return; }
8
10
  const {
9
11
  cachePassword = DEFAULT_CACHE_PASSWORD,
10
12
  cacheProtocol = CACHE_PROTOCOL.LOCAL_STORAGE,
11
- io
13
+ io,
14
+ promoteCache
12
15
  } = Scoped.ReleaseCacheData;
13
16
 
14
17
  clearTimeout(Scoped.cacheStorageReducer);
15
18
  Scoped.cacheStorageReducer = setTimeout(() => {
19
+ const { AuthStore, DatabaseStore, PendingWrites, ...restStore } = CacheStore;
20
+
16
21
  const txt = encryptString(
17
- JSON.stringify({ ...CacheStore }),
22
+ JSON.stringify({
23
+ AuthStore,
24
+ ...promoteCache ? {
25
+ DatabaseStore: serializeToBase64(DatabaseStore),
26
+ PendingWrites: serializeToBase64(PendingWrites)
27
+ } : {},
28
+ ...promoteCache ? restStore : {}
29
+ }),
18
30
  cachePassword,
19
31
  cachePassword
20
32
  );
@@ -24,8 +36,8 @@ export const updateCacheStore = () => {
24
36
  } else if (cacheProtocol === CACHE_PROTOCOL.LOCAL_STORAGE) {
25
37
  window.localStorage.setItem(CACHE_STORAGE_PATH, txt);
26
38
  }
27
- }, 500);
28
- }
39
+ }, timer);
40
+ };
29
41
 
30
42
  export const releaseCacheStore = async (builder) => {
31
43
  try { window } catch (_) { return; }
@@ -44,17 +56,26 @@ export const releaseCacheStore = async (builder) => {
44
56
  }
45
57
 
46
58
  const j = JSON.parse(decryptString(txt || '', cachePassword, cachePassword) || '{}');
59
+ const projectList = new Set([]);
47
60
 
48
61
  Object.entries(j).forEach(([k, v]) => {
49
- CacheStore[k] = v;
62
+ if (['DatabaseStore', 'PendingWrites'].includes(k)) {
63
+ CacheStore[k] = deserializeBSON(v);
64
+ } else CacheStore[k] = v;
65
+ projectList.add(k);
50
66
  });
51
67
  Object.entries(CacheStore.AuthStore).forEach(([key, value]) => {
52
68
  Scoped.AuthJWTToken[key] = value?.token;
53
69
  });
70
+ projectList.forEach(projectUrl => {
71
+ if (Scoped.IS_CONNECTED[projectUrl])
72
+ trySendPendingWrite(projectUrl);
73
+ });
54
74
  Scoped.IsStoreReady = true;
55
75
  StoreReadyListener.dispatch('_', 'ready');
56
- // TODO: commit pending write
57
- }
76
+ };
77
+
78
+ export const getPrefferTime = () => Date.now() + (Scoped.serverTimeOffset || 0);
58
79
 
59
80
  export const awaitStore = () => new Promise(resolve => {
60
81
  if (Scoped.IsStoreReady) {
@@ -109,12 +130,4 @@ export const buildFetchInterface = ({ body, accessKey, authToken, method, uglify
109
130
  },
110
131
  method: method || 'POST'
111
132
  }, keyPair];
112
- };
113
-
114
- export const simplifyError = (error, message) => ({
115
- simpleError: { error, message }
116
- });
117
-
118
- export const validateRequestMethod = (method) => {
119
- // TODO:
120
- }
133
+ };
@@ -1,10 +1,7 @@
1
1
  import { encodeBinary } from './peripherals';
2
2
 
3
3
  export const CACHE_STORAGE_PATH = encodeBinary('MOSQUITO_TRANSPORT_FREEZER'),
4
- DEFAULT_CACHE_PASSWORD = encodeBinary('MOSQUITO_TRANSPORT_CACHE_PASSWORD'),
5
- DEFAULT_DB_NAME = 'DEFAULT_DB',
6
- DEFAULT_DB_URL = 'mongodb://127.0.0.1:27017',
7
- DEFAULT_ENCRYPT_IV = '****';
4
+ DEFAULT_CACHE_PASSWORD = encodeBinary('MOSQUITO_TRANSPORT_CACHE_PASSWORD');
8
5
 
9
6
  export const CACHE_PROTOCOL = {
10
7
  LOCAL_STORAGE: 'local-storage'
@@ -16,7 +13,8 @@ export const RETRIEVAL = {
16
13
  STICKY_RELOAD: 'sticky-reload',
17
14
  DEFAULT: 'default',
18
15
  CACHE_NO_AWAIT: 'cache-no-await',
19
- NO_CACHE_NO_AWAIT: 'no-cache-no-await'
16
+ NO_CACHE_NO_AWAIT: 'no-cache-no-await',
17
+ NO_CACHE_AWAIT: 'no-cache-await'
20
18
  };
21
19
 
22
20
  export const DELIVERY = {
@@ -28,43 +26,6 @@ export const DELIVERY = {
28
26
  CACHE_NO_AWAIT: 'cache-no-await'
29
27
  };
30
28
 
31
- export const WRITE_OPS = {
32
- $SET: '$set',
33
- $PUSH: '$push',
34
- $PULL: '$pull',
35
- $UNSET: '$unset',
36
- $INC: '$inc',
37
- $MAX: '$max',
38
- $MIN: '$min',
39
- $MUL: '$mul',
40
- $RENAME: '$rename',
41
- $SET_ON_INSERT: '$setOnInsert'
42
- };
43
- export const WRITE_OPS_LIST = Object.values(WRITE_OPS);
44
-
45
- export const READ_OPS = {
46
- $IN: '$in',
47
- $ALL: '$all',
48
- $NIN: '$nin',
49
- $GT: '$gt',
50
- $GTE: '$gte',
51
- $LT: '$lt',
52
- $LTE: '$lte',
53
- $TEXT: '$text',
54
- // $EQ: '$eq',
55
- // $REGEX: '$regex',
56
- // $EXISTS: '$exists',
57
- $NEAR: '$near',
58
- $TYPE: '$type',
59
- $SIZE: '$size',
60
- // $NE: '$ne'
61
- };
62
- export const READ_OPS_LIST = Object.values(READ_OPS);
63
-
64
- export const Regexs = {
65
- LINK: () => /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig
66
- };
67
-
68
29
  export const AUTH_PROVIDER_ID = {
69
30
  GOOGLE: 'google.com',
70
31
  FACEBOOK: 'facebook.com',
@@ -1,4 +1,6 @@
1
+
1
2
  export const Scoped = {
3
+ serverTimeOffset: undefined,
2
4
  PendingIte: 0,
3
5
  AnyProcessIte: 0,
4
6
  IS_CONNECTED: {},
@@ -19,16 +21,21 @@ export const Scoped = {
19
21
  PendingDbReadCollective: {
20
22
  pendingProcess: {},
21
23
  pendingResolution: {}
22
- }
23
- }
24
+ },
25
+ ActiveDatabaseListeners: {},
26
+ OutgoingWrites: {},
27
+ /**
28
+ * @type {Promise<any> | undefined}
29
+ */
30
+ dispatchingWritesPromise: undefined,
31
+ broadcastedWrites: {}
32
+ };
24
33
 
25
34
  export const CacheStore = {
26
35
  DatabaseStore: {},
27
- DatabaseRecords: {},
28
36
  DatabaseCountResult: {},
37
+ DatabaseStats: {},
29
38
  AuthStore: {},
30
39
  PendingWrites: {},
31
40
  FetchedStore: {}
32
- }
33
-
34
- export const CacheConstant = { ...CacheStore };
41
+ };
package/src/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  interface MTConfig {
2
2
  dbName?: string;
3
3
  dbUrl?: string;
4
- heapMemory?: number;
5
4
  projectUrl: string;
6
5
  disableCache?: boolean;
7
6
  accessKey: string;
7
+ /**
8
+ * maximum numbers of attempts to retry sending a request
9
+ */
8
10
  maxRetries?: number;
9
11
  /**
10
12
  * setting this to true will encrypt all outgoing and incoming request. This enables end-to-end encryption using [Tweetnacl](https://github.com/dchest/tweetnacl-js) and to prevent request interception by browser extensions, network intermediaries or other hijacking tools
@@ -14,6 +16,12 @@ interface MTConfig {
14
16
  * this is the base64 public key for end-to-end encryption on the server
15
17
  */
16
18
  serverE2E_PublicKey?: string;
19
+ /**
20
+ * true to deserialize BSON values to their Node.js closest equivalent types
21
+ *
22
+ * @default true
23
+ */
24
+ castBSON?: boolean;
17
25
  }
18
26
 
19
27
  interface GetDatabase {
@@ -34,7 +42,7 @@ export function GEO_JSON(latitude: latitude, longitude: longitude): {
34
42
  };
35
43
 
36
44
  export function FIND_GEO_JSON(coordinates: [latitude, longitude], offSetMeters: number, centerMeters?: number): {
37
- $near: {
45
+ $nearSphere: {
38
46
  $geometry: {
39
47
  type: "Point",
40
48
  coordinates: [longitude, latitude]
@@ -76,7 +84,7 @@ interface ReleaseCacheOption_IO {
76
84
  * emits mosquito-transport internal data
77
85
  */
78
86
  output: (data: string) => void;
79
- }
87
+ };
80
88
  }
81
89
 
82
90
  interface ReleaseCacheOption {
@@ -88,7 +96,18 @@ interface ReleaseCacheOption {
88
96
  * select the mechanism for storing data locally
89
97
  * - local-storage: uses [@react-native-async-storage/async-storage]() for storing data
90
98
  */
91
- cacheProtocol?: 'local-storage';
99
+ cacheProtocol?: 'local-storage' | 'indexdb';
100
+ /**
101
+ * the maximum database size
102
+ */
103
+ heapMemory?: number;
104
+ /**
105
+ * true to cache database and {@link MosquitoTransport.fetchHttp} data.
106
+ * the value only applies to in-memory storage protocol such as `io` and `local-storage`
107
+ *
108
+ * @default false
109
+ */
110
+ promoteCache?: boolean;
92
111
  }
93
112
 
94
113
  interface MTSocket {
@@ -243,7 +262,7 @@ interface WriteConfig {
243
262
  delivery?: Delievery;
244
263
  }
245
264
 
246
- type Retrieval = 'sticky' | 'sticky-no-await' | 'sticky-reload' | 'default' | 'cache-no-await' | 'no-cache-no-await';
265
+ type Retrieval = 'sticky' | 'sticky-no-await' | 'sticky-reload' | 'default' | 'cache-no-await' | 'no-cache-no-await' | 'no-cache-await';
247
266
 
248
267
  interface GetConfig {
249
268
  excludeFields?: string | string[];
@@ -252,17 +271,19 @@ interface GetConfig {
252
271
  /**
253
272
  * This property determines how requested data is being access and handled
254
273
  *
255
- * - default: we try getting fresh data from server if server is reachable, else we check if local data exists and return it, if no local data exist we await for client->server connectivity, then try getting the data, return it and cache it for future need. ⚠️ This respect disableCache value
274
+ * - default: will try getting fresh data from server if server is reachable, else we check if local data exists and return it, if no local data exist we await for client->server connectivity, then try getting the data, return it and cache it for future need. ⚠️ This respect disableCache value
256
275
  *
257
276
  * - sticky: if local data exists for the specified query, such data is returned and no-ops afterwards. If no local data is found, we await for client->server connectivity and try to get fresh data from serve, return the data and cache it for future need. ⚠️ This does not respect disableCache value
258
277
  *
259
- * - sticky-no-await: if local data exists for the specified query, such data is returned and no-ops afterwards. If no local data is found, we try to get fresh data from serve, we throw an error if server is not reachable else if server returns requested data, we return such data and cache it for future need. ⚠️ This does not respect disableCache value
278
+ * - sticky-no-await: if local data exists for the specified query, such data is returned and no-ops afterwards. If no local data is found, will try to get fresh data from serve, we throw an error if server is not reachable else if server returns requested data, we return such data and cache it for future need. ⚠️ This does not respect disableCache value
279
+ *
280
+ * - sticky-reload: if local data exists for the specified query, such data is returned, then will try getting fresh data from the server and caching it for future need. If no local data is found, we await for client->server connectivity and try to get fresh data from serve, return the data and cache it for future need
260
281
  *
261
- * - sticky-reload: if local data exists for the specified query, such data is returned, then we try getting fresh data from the server and caching it for future need. If no local data is found, we await for client->server connectivity and try to get fresh data from serve, return the data and cache it for future need
282
+ * - cache-no-await: will try getting fresh data from server if server is reachable, else we check if local data exists and return it, if no local data exist we throw an error
262
283
  *
263
- * - cache-no-await: we try getting fresh data from server if server is reachable, else we check if local data exists and return it, if no local data exist we throw an error
284
+ * - no-cache-no-await: will try getting fresh data from server if server is reachable, else we throw an error
264
285
  *
265
- * - no-cache-no-await: we try getting fresh data from server if server is reachable, else we throw an error
286
+ * - no-cache-await: will try getting fresh data from server when server is reachable and the result won't be cache
266
287
  *
267
288
  * To learn and see more examples on this, Please visit https://brainbehindx.com/mosquito-transport/docs/reading_data/retrieval
268
289
  */
@@ -417,11 +438,12 @@ declare type Base64String = string;
417
438
 
418
439
  interface ReqOptions {
419
440
  awaitServer?: boolean;
441
+ createHash?: boolean;
420
442
  }
421
443
 
422
444
  interface MTStorage {
423
445
  downloadFile: (link: string, onComplete?: (error?: ErrorResponse, filepath?: string) => void, destination?: string, onProgress?: (stats: DownloadProgressStats) => void) => () => void;
424
- uploadFile: (file: Base64String | Blob | Buffer, destination: string, onComplete?: (error?: ErrorResponse, downloadUrl?: string) => void, onProgress?: (stats: UploadProgressStats) => void, options?: ReqOptions) => () => void;
446
+ uploadFile: (file: Base64String | Blob | Buffer | File, destination: string, onComplete?: (error?: ErrorResponse, downloadUrl?: string) => void, onProgress?: (stats: UploadProgressStats) => void, options?: ReqOptions) => () => void;
425
447
  deleteFile: (path: string) => Promise<void>;
426
448
  deleteFolder: (folder: string) => Promise<void>;
427
449
  }