react-native-mosquito-transport 0.0.28 → 0.0.30

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,11 +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
+ - avoid sending cookies
24
24
  <!-- - error: "refreshToken retry limit exceeded" <--- no need -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mosquito-transport",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
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",
@@ -33,7 +33,6 @@
33
33
  "entity-serializer": "^1.0.3",
34
34
  "guard-object": "^1.1.4",
35
35
  "lodash": "^4.17.21",
36
- "react-native-get-random-values": "^1.9.0",
37
36
  "simplify-error": "^1.0.1",
38
37
  "socket.io-client": "^4.6.2",
39
38
  "subscription-listener": "^1.1.2",
@@ -42,9 +41,10 @@
42
41
  "peerDependencies": {
43
42
  "react": "*",
44
43
  "react-native": "*",
45
- "react-native-file-access": "*",
44
+ "react-native-fs": "*",
46
45
  "react-native-sha256": "*",
47
- "react-native-sqlite-storage": "*"
46
+ "react-native-sqlite-storage": "*",
47
+ "react-native-get-random-values": "*"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/react-native-sqlite-storage": "^6.0.5"
@@ -1,28 +1,37 @@
1
1
  import { Platform } from "react-native";
2
2
  import { Buffer } from 'buffer';
3
3
  import { deserialize, serialize } from 'entity-serializer';
4
- import { Dirs, FileSystem } from 'react-native-file-access';
4
+ import { writeFile, mkdir, MainBundlePath, readFile, unlink, DocumentDirectoryPath } from "react-native-fs";
5
5
 
6
6
  const MAX_INLINE_BLOB = 1024;
7
7
 
8
- const DIR_PATH = `${Platform.OS === 'android' ? Dirs.DatabaseDir : Dirs.MainBundleDir}/MOSQUITO`;
9
- const resolvePath = (path = '') => `${DIR_PATH}/${path.startsWith('/') ? path : '/' + path}`;
8
+ const DIR_PATH = `${Platform.OS === 'android' ? DocumentDirectoryPath.split('/').slice(0, -1).join('/').concat('/databases') : MainBundlePath}/MOSQUITO`;
9
+ const resolvePath = (path = '') => `${DIR_PATH}${path.startsWith('/') ? path : '/' + path}`;
10
10
 
11
- const DIR_CREATION_PROMISE = FileSystem.mkdir(DIR_PATH).catch(() => null);
11
+ const DIR_CREATION_PROMISE = mkdir(DIR_PATH).catch(() => null);
12
12
 
13
13
  const fsWrite = async (path, data) => {
14
14
  await DIR_CREATION_PROMISE;
15
- return FileSystem.writeFile(resolvePath(path), data instanceof Buffer ? data.toString('base64') : data, 'base64');
15
+ return writeFile(resolvePath(path), data instanceof Buffer ? data.toString('base64') : data, 'base64');
16
16
  }
17
17
 
18
18
  const fsRead = async (path) => {
19
19
  await DIR_CREATION_PROMISE;
20
- return Buffer.from(await FileSystem.readFile(resolvePath(path), 'base64'), 'base64');
20
+ return Buffer.from(await readFile(resolvePath(path), 'base64'), 'base64');
21
21
  }
22
22
 
23
- export const getStoreID = (db_filename, table, primary_key) => `${table}_${primary_key}_${db_filename}.blob`;
23
+ const purifyFilename = (filename) => {
24
+ if (!filename || typeof filename !== 'string') return 'unnamed';
24
25
 
25
- export const deleteBigData = (store_id) => FileSystem.unlink(resolvePath(store_id));
26
+ // Remove invalid characters for both iOS and Android
27
+ return filename
28
+ .replace(/[/\\?%*:|"<>]/g, '') // Remove forbidden characters
29
+ .trim(); // Remove leading/trailing whitespace
30
+ }
31
+
32
+ export const getStoreID = (db_filename, table, primary_key) => purifyFilename(`${table}_${primary_key}_${db_filename}.blob`);
33
+
34
+ export const deleteBigData = (store_id) => unlink(resolvePath(store_id));
26
35
 
27
36
  export const handleBigData = async (store_id, data) => {
28
37
  const bufData = serialize(data);
@@ -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
 
@@ -137,7 +137,7 @@ export const SQLITE_PATH = {
137
137
  };
138
138
 
139
139
  export const SQLITE_COMMANDS = {
140
- MERGE: (table, columns = []) => `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${columns.map(() => '?').join(', ')}) ON CONFLICT(${columns[0]}) DO UPDATE SET ${columns.slice(1).map(v => `${v} = excluded.${v}`).join(', ')}`,
140
+ MERGE: (table, columns = []) => `INSERT OR REPLACE INTO ${table} (${columns.join(', ')}) VALUES (${columns.fill('?').join(', ')})`,
141
141
  UPDATE_COLUMNS: (table, columns = [], query = '') => `UPDATE ${table} SET ${columns.map(v => `${v} = ?`).join(', ')} WHERE ${query}`,
142
142
  CREATE_INDEX: (table, columns) => `CREATE INDEX idx_${columns.join('_')} ON ${table}(${columns.join(', ')})`,
143
143
  DELETE_ROW: (table, query) => `DELETE FROM ${table} WHERE ${query}`
@@ -164,7 +164,8 @@ export const buildFetchInterface = async ({ body, authToken, method, uglify, ser
164
164
  'Content-type': uglify ? 'request/buffer' : 'application/json',
165
165
  ...(authToken && !uglify) ? { 'Mosquito-Token': authToken } : {}
166
166
  },
167
- method: method || 'POST'
167
+ method: method || 'POST',
168
+ credentials: 'omit'
168
169
  }, keyPair];
169
170
  };
170
171
 
package/src/index.d.ts CHANGED
@@ -427,7 +427,7 @@ interface DocumentWriteValue {
427
427
 
428
428
  interface RNMTAuth {
429
429
  customSignin: (email: string, password: string) => Promise<SigninResult>;
430
- customSignup: (email: string, password: string, name?: string, metadata?: Object) => Promise<SigninResult>;
430
+ customSignup: (email: string, password: string, name?: string, metadata?: Object) => Promise<SignupResult>;
431
431
  googleSignin: (token: string) => Promise<SignupResult>;
432
432
  appleSignin: () => Promise<SignupResult>;
433
433
  facebookSignin: () => Promise<SignupResult>;
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 @@ class RNMT {
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 @@ class RNMT {
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) => {
@@ -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)
@@ -57,7 +57,7 @@ export const insertCountQuery = async (builder, access_id, value) => {
57
57
  Scoped.initedSqliteInstances.dbQueryCount[initNode] = (async () => {
58
58
  await sqlite.executeSql(`CREATE TABLE IF NOT EXISTS ${DB_COUNT_QUERY(path)} ( access_id TEXT PRIMARY KEY, value TEXT, touched INTEGER )`).catch(() => null);
59
59
  await Promise.allSettled([
60
- sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(DB_COUNT_QUERY(path), ['access_id'])),
60
+ // sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(DB_COUNT_QUERY(path), ['access_id'])),
61
61
  // sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(DB_COUNT_QUERY(path), ['touched']))
62
62
  ]);
63
63
  })();
@@ -117,9 +117,9 @@ export const insertRecord = async (builder, config, accessIdWithoutLimit, value,
117
117
  ]);
118
118
 
119
119
  await Promise.allSettled([
120
- sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(LIMITER_DATA(path), ['access_id'])),
120
+ // sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(LIMITER_DATA(path), ['access_id'])),
121
121
  // sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(LIMITER_DATA(path), ['touched'])),
122
- sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(LIMITER_RESULT(path), ['access_id_limiter'])),
122
+ // sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(LIMITER_RESULT(path), ['access_id_limiter'])),
123
123
  // sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX(LIMITER_RESULT(path), ['touched']))
124
124
  ]);
125
125
  })();
@@ -31,8 +31,8 @@ export const insertFetchResources = async (projectUrl, access_id, value) => {
31
31
  Scoped.initedSqliteInstances.httpFetch[initNode] = (async () => {
32
32
  await sqlite.executeSql(`CREATE TABLE IF NOT EXISTS main ( access_id TEXT PRIMARY KEY, value BLOB, touched INTEGER, size INTEGER )`).catch(() => null);
33
33
  await Promise.allSettled([
34
- sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX('main', ['access_id'])),
35
- sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX('main', ['touched']))
34
+ // sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX('main', ['access_id'])),
35
+ // sqlite.executeSql(SQLITE_COMMANDS.CREATE_INDEX('main', ['touched']))
36
36
  ]);
37
37
  })();
38
38
  }
@@ -143,6 +143,7 @@ export const mfetch = async (input = '', init, config) => {
143
143
 
144
144
  const f = await fetch(isLink ? input : `${projectUrl}/${normalizeRoute(input)}`, {
145
145
  ...(!isBaseUrl || hasBody) ? { method: 'POST' } : {},
146
+ credentials: 'omit',
146
147
  ...init,
147
148
  ...uglified ? { body: reqBuilder } : encodeBody ? { body: serialize(body) } : {},
148
149
  // cache: 'no-cache',