react-native-mosquito-transport 0.0.19 → 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.
package/.jshintignore ADDED
@@ -0,0 +1,4 @@
1
+ node_modules/
2
+ android/
3
+ example/
4
+ ios/
package/.jshintrc ADDED
@@ -0,0 +1,16 @@
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
+ "URL": true
15
+ }
16
+ }
package/README.md CHANGED
@@ -1 +1,71 @@
1
- # react-native-mosquito-transport
1
+ # react-native-mosquito-transport
2
+
3
+ React native javascript sdk for [mosquito-transport](https://github.com/brainbehindx/mosquito-transport).
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ npm install react-native-mosquito-transport --save
9
+ ```
10
+
11
+ or using yarn
12
+
13
+ ```sh
14
+ yarn add react-native-mosquito-transport
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```js
20
+ import RNMosquitoTransport from "react-native-mosquito-transport";
21
+
22
+ // uses sqlite to cache it data by default
23
+ RNMosquitoTransport.initializeCache();
24
+
25
+ const mclient = new RNMosquitoTransport({
26
+ projectUrl: "http://localhost:3444"
27
+ });
28
+ ```
29
+
30
+ ## Additional Documentations
31
+
32
+ - [RNMosquitoTransport Constructor](#RNMosquitoTransportConstructor)
33
+ - [dbName](#dbName)
34
+ - [dbUrl](#dbUrl)
35
+ - [projectUrl](#projectUrl)
36
+ - [disableCache](#disableCache)
37
+ - [maxRetries](#maxRetries)
38
+ - [enableE2E_Encryption](#enableE2E_Encryption)
39
+ - [serverE2E_PublicKey](#serverE2E_PublicKey)
40
+ - [extraHeaders](#extraHeaders)
41
+ - [castBSON](#castBSON)
42
+ - [RNMosquitoTransport Methods](#RNMosquitoTransportMethods)
43
+ - [initialCache](#initialCache)
44
+ - [getDatabase](#getDatabase)
45
+ - [collection](#collection)
46
+ - [auth](#auth)
47
+ - [storage](#storage)
48
+ - [fetchHttp](#fetchHttp)
49
+ - [listenReachableServer](#listenReachableServer)
50
+ - [getSocket](#getSocket)
51
+ - [batchWrite](#batchWrite)
52
+ - [TIMESTAMP](#TIMESTAMP)
53
+ - [AUTH_PROVIDER_ID](#AUTH_PROVIDER_ID)
54
+ - [DOCUMENT_EXTRACTION](#DOCUMENT_EXTRACTION)
55
+ - [GEO_JSON](#GEO_JSON)
56
+ - [FIND_GEO_JSON](#FIND_GEO_JSON)
57
+ - [DoNotEncrypt](#DoNotEncrypt)
58
+
59
+ ## RNMosquitoTransport Constructor
60
+
61
+ ### dbName
62
+
63
+
64
+ ### dbUrl
65
+
66
+
67
+ ### projectUrl
68
+
69
+ this is the base url of
70
+
71
+ ### disableCache
package/TODO CHANGED
@@ -1,6 +1,23 @@
1
- - fix local cache query on sqlite and fs
1
+ - fix local cache query on sqlite
2
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
- - change null to undefined in `value`
6
+ - change undefined to null in `value`
7
+ - `provide functionality to add extra header to MT instance (all outgoing request)` ✅
8
+ - borrowToken
9
+ - `add sqlite` ✅
10
+ - minimize extraction data ✅
11
+ - change `collection().onDisconnect()` to `collection().socket().onDisconnect()` and `collection().socket().onConnect()` ✅
12
+ - add `_foreign_doc` to d.ts ✅
13
+ - tree shake dependencies
14
+ - dynamic import for fs ✅
15
+ - new URL() work around ✅
16
+ - fetchHttp, default retrieval if has body ✅
17
+ - native hashing
18
+ - TextEncoder
19
+ - native storage upload
20
+ - lodashes ✅
21
+ - switch to events package
22
+ - serverTimeOffset
23
+ <!-- - error: "refreshToken retry limit exceeded" <--- no need -->
@@ -88,18 +88,23 @@ class MosquitodbUploadTask: NSObject, URLSessionDataDelegate {
88
88
  let filepath = options["file"] as! String
89
89
  let url = options["url"] as! String
90
90
  let destination = options["destination"] as! String
91
- let authorization = options["authorization"] as! String
92
91
 
93
92
  do {
94
93
  let rawData = try Data(contentsOf: URL(fileURLWithPath: filepath))
95
94
 
96
95
  var request = URLRequest(url: URL(string: url)!)
97
96
  request.httpMethod = "POST"
97
+
98
+ if let extraHeaders = options["extraHeaders"] as? [[String: String]] {
99
+ for (key, value) in extraHeaders {
100
+ request.setValue(value, forHTTPHeaderField: key)
101
+ }
102
+ }
98
103
  request.setValue("application/json", forHTTPHeaderField: "Accept")
99
- request.setValue(authorization, forHTTPHeaderField: "Authorization")
100
104
  if options["authToken"] != nil {
101
105
  request.setValue(options["authToken"] as? String, forHTTPHeaderField: "Mosquito-Token")
102
106
  }
107
+ request.setValue(options["createHash"] as? String, forHTTPHeaderField: "hash-upload");
103
108
  request.setValue("buffer/upload", forHTTPHeaderField: "Content-Type")
104
109
  request.setValue(destination, forHTTPHeaderField: "Mosquito-Destination")
105
110
 
@@ -183,11 +188,15 @@ class MosquitodbDownloadTask: NSObject, URLSessionDownloadDelegate {
183
188
  func downloadFile(options: [String: Any], completion: @escaping ([Any]?)->()) -> Void {
184
189
  let processID = options["processID"] as! String
185
190
  let url = options["url"] as! String
186
- let authorization = options["authorization"] as! String
187
191
 
188
192
  var request = URLRequest(url: URL(string: url)!)
189
193
  request.httpMethod = "POST"
190
- request.setValue(authorization, forHTTPHeaderField: "Authorization")
194
+
195
+ if let extraHeaders = options["extraHeaders"] as? [[String: String]] {
196
+ for (key, value) in extraHeaders {
197
+ request.setValue(value, forHTTPHeaderField: key)
198
+ }
199
+ }
191
200
  if options["authToken"] != nil {
192
201
  request.setValue(options["authToken"] as? String, forHTTPHeaderField: "Mosquito-Token")
193
202
  }
@@ -249,7 +258,7 @@ class MosquitodbDownloadTask: NSObject, URLSessionDownloadDelegate {
249
258
  "result": "{\"file\": \"\(dest)\"}"
250
259
  ]
251
260
  ])
252
- }else{
261
+ } else {
253
262
  let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
254
263
  let urlName = mainOptions["urlName"] as! String
255
264
  let destDir = documentsURL.appendingPathComponent("mosquito-transport")
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "react-native-mosquito-transport",
3
- "version": "0.0.19",
4
- "description": "React native javascript sdk for mosquito-transport (https://github.com/deflexable/mosquito-transport)",
3
+ "version": "0.0.22",
4
+ "description": "React native javascript sdk for mosquito-transport (https://github.com/brainbehindx/mosquito-transport)",
5
5
  "main": "src/index.js",
6
+ "type": "module",
6
7
  "scripts": {
7
8
  "test": "echo \"Error: no test specified\" && exit 1"
8
9
  },
9
10
  "repository": {
10
11
  "type": "git",
11
- "url": "git+https://github.com/deflexable/react-native-mosquito-transport.git"
12
+ "url": "git+https://github.com/brainbehindx/react-native-mosquito-transport.git"
12
13
  },
13
14
  "keywords": [
14
15
  "mosquito-transport",
@@ -22,23 +23,19 @@
22
23
  "author": "Anthony Onabanjo <deflexable@gmail.com> (https://github.com/deflexable)",
23
24
  "license": "MIT",
24
25
  "bugs": {
25
- "url": "https://github.com/deflexable/react-native-mosquito-transport/issues"
26
+ "url": "https://github.com/brainbehindx/react-native-mosquito-transport/issues"
26
27
  },
27
- "homepage": "https://github.com/deflexable/react-native-mosquito-transport#readme",
28
+ "homepage": "https://github.com/brainbehindx/react-native-mosquito-transport#readme",
28
29
  "dependencies": {
29
- "@types/crypto-js": "^4.2.1",
30
- "@types/lodash": "^4.14.194",
30
+ "@turf/turf": "^7.1.0",
31
+ "bson": "^6.8.0",
31
32
  "buffer": "^6.0.3",
32
- "crypto-js": "^4.2.0",
33
- "fast-json-stable-stringify": "^2.1.0",
34
- "guard-object": "^1.0.9",
35
- "json-buffer": "^3.0.1",
36
- "lodash.get": "^4.4.2",
37
- "lodash.isequal": "^4.5.0",
38
- "lodash.set": "^4.3.2",
39
- "lodash.unset": "^4.5.2",
33
+ "entity-serializer": "^1.0.2",
34
+ "guard-object": "^1.1.4",
35
+ "lodash": "^4.17.21",
40
36
  "react-native-get-random-values": "^1.9.0",
41
- "set-large-timeout": "^1.0.1",
37
+ "react-native-hash": "^3.0.3",
38
+ "simplify-error": "^1.0.1",
42
39
  "socket.io-client": "^4.6.2",
43
40
  "subscription-listener": "^1.1.2",
44
41
  "tweetnacl": "^1.0.3"
@@ -46,5 +43,8 @@
46
43
  "peerDependencies": {
47
44
  "react": "*",
48
45
  "react-native": "*"
46
+ },
47
+ "devDependencies": {
48
+ "@types/react-native-sqlite-storage": "^6.0.5"
49
49
  }
50
- }
50
+ }
@@ -0,0 +1,34 @@
1
+ import { encodeBinary } from './peripherals';
2
+
3
+ const EngineApiBase = (baseApi, ugly, path) =>
4
+ ugly ? `${baseApi}/e2e/${encodeBinary(path)}` : `${baseApi}/${path}`;
5
+
6
+ const apis = {
7
+ _readDocument: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_readDocument'),
8
+ _queryCollection: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_queryCollection'),
9
+ _documentCount: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_documentCount'),
10
+ _writeDocument: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_writeDocument'),
11
+ _writeMapDocument: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_writeMapDocument'),
12
+ _customSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_customSignin'),
13
+ _customSignup: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_customSignup'),
14
+ _googleSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_googleSignin'),
15
+ _appleSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_appleSignin'),
16
+ _facebookSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_facebookSignin'),
17
+ _twitterSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_twitterSignin'),
18
+ _githubSignin: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_githubSignin'),
19
+ _signOut: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_signOut'),
20
+ _refreshAuthToken: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_refreshAuthToken'),
21
+ _uploadFile: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_uploadFile'),
22
+ _deleteFile: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_deleteFile'),
23
+ _deleteFolder: (baseApi, ugly) => EngineApiBase(baseApi, ugly, '_deleteFolder'),
24
+ staticStorage: (baseApi) => `${baseApi}/storage`,
25
+ _areYouOk: (baseApi) => `${baseApi}/_areYouOk`,
26
+ // static path
27
+ _listenCollection: (ugly) => ugly ? encodeBinary(apis._listenCollection()) : '_listenCollection',
28
+ _listenDocument: (ugly) => ugly ? encodeBinary(apis._listenDocument()) : '_listenDocument',
29
+ _startDisconnectWriteTask: (ugly) => ugly ? encodeBinary(apis._startDisconnectWriteTask()) : '_startDisconnectWriteTask',
30
+ _cancelDisconnectWriteTask: (ugly) => ugly ? encodeBinary(apis._cancelDisconnectWriteTask()) : '_cancelDisconnectWriteTask',
31
+ _listenUserVerification: (ugly) => ugly ? encodeBinary(apis._listenUserVerification()) : '_listenUserVerification'
32
+ };
33
+
34
+ export default { ...apis };
@@ -1,133 +1,46 @@
1
1
  import { Buffer } from "buffer";
2
2
  import { ServerReachableListener } from "./listeners";
3
- import aes_pkg from 'crypto-js/aes.js';
4
- import Utf8Encoder from 'crypto-js/enc-utf8.js';
5
3
  import naclPkg from 'tweetnacl';
4
+ import getLodash from "lodash/get";
5
+ import { deserialize, serialize } from "entity-serializer";
6
+ import { CONSTANTS, JSHash } from 'react-native-hash';
6
7
 
7
- const { encrypt, decrypt } = aes_pkg;
8
8
  const { box, randomBytes } = naclPkg;
9
9
 
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
10
  export const listenReachableServer = (callback, projectUrl) => {
102
11
  let lastValue;
103
12
  return ServerReachableListener.listenTo(projectUrl, t => {
104
13
  if (typeof t === 'boolean' && t !== lastValue) callback?.(t);
105
14
  }, true);
106
- }
15
+ };
107
16
 
108
17
  export const prefixStoragePath = (path, prefix = 'file:///') => {
109
- if (!path) return path;
18
+ let cleanedPath = path.replace(/^[^/]+:\/{1,3}/, '');
110
19
 
111
- if (!path.startsWith('/') && !path.includes(':')) return prefix + path;
20
+ // Continuously remove any remaining protocol patterns until none are left
21
+ while (/^[^/]+:\/{1,3}/.test(cleanedPath)) {
22
+ cleanedPath = cleanedPath.replace(/^[^/]+:\/{1,3}/, '');
23
+ }
112
24
 
113
- return prefix + path.split('/').filter((v, i) => i && v).join('/');
114
- }
25
+ // Remove any leading slashes after protocol removal
26
+ cleanedPath = cleanedPath.replace(/^\/+/, '');
115
27
 
116
- export const getUrlExtension = (url) => {
117
- const r = url.split(/[#?]/)[0].split(".").pop().trim();
118
- return r === url ? '' : r;
119
- }
28
+ return `${prefix}${cleanedPath}`;
29
+ };
120
30
 
121
31
  export const niceTry = (promise) => new Promise(async resolve => {
122
-
123
32
  try {
124
33
  const r = await promise();
125
34
  resolve(r);
126
35
  } catch (e) { resolve(); }
127
36
  });
128
37
 
38
+ export const normalizeRoute = (route = '') => route.split('').map((v, i, a) =>
39
+ ((!i && v === '/') || (i === a.length - 1 && v === '/') || (i && a[i - 1] === '/' && v === '/')) ? '' : v
40
+ ).join('');
41
+
129
42
  export const shuffleArray = (n) => {
130
- const array = [...n];
43
+ const array = n.slice(0);
131
44
  let currentIndex = array.length, randomIndex;
132
45
 
133
46
  while (currentIndex != 0) {
@@ -143,56 +56,65 @@ export const shuffleArray = (n) => {
143
56
  }
144
57
 
145
58
  export function sortArrayByObjectKey(arr = [], key) {
146
- return arr.slice(0).sort(function (a, b) {
59
+ return arr.sort(function (a, b) {
147
60
  const left = getLodash(a, key),
148
61
  right = getLodash(b, key);
149
62
 
150
63
  return (left > right) ? 1 : (left < right) ? -1 : 0;
151
64
  });
152
- }
65
+ };
153
66
 
154
- export const encryptString = (txt, password, iv) => {
155
- return encrypt(txt, `${password || ''}${iv || ''}`).toString();
156
- }
67
+ export async function niceHash(str = '') {
68
+ const hash = await JSHash(str, CONSTANTS.HashAlgorithms.md5);
69
+ if (hash.length > str.length) return encodeBinary(str);
70
+ return hash;
71
+ };
157
72
 
158
- export const decryptString = (txt, password, iv) => {
159
- return decrypt(txt, `${password || ''}${iv || ''}`).toString(Utf8Encoder);
160
- }
73
+ export const sameInstance = (var1, var2) => {
74
+ try {
75
+ return var1.constructor === var2.constructor &&
76
+ Object.getPrototypeOf(var1) === Object.getPrototypeOf(var2)
77
+ } catch (_) {
78
+ return false;
79
+ }
80
+ };
161
81
 
162
- export const serializeE2E = (data, auth_token, serverPublicKey) => {
82
+ export const serializeE2E = async (data, auth_token, serverPublicKey) => {
163
83
  const pair = box.keyPair(),
164
- nonce = randomBytes(box.nonceLength),
165
- pubBase64 = Buffer.from(pair.publicKey).toString('base64'),
166
- nonceBase64 = Buffer.from(nonce).toString('base64');
84
+ nonce = randomBytes(box.nonceLength);
167
85
 
168
86
  return [
169
- `${pubBase64}.${nonceBase64}.${Buffer.from(
170
- box(
171
- Buffer.from(JSON.stringify([
172
- data,
173
- auth_token
174
- ]), 'utf8'),
175
- nonce,
176
- Buffer.from(serverPublicKey, 'base64'),
177
- pair.secretKey
87
+ serialize([
88
+ pair.publicKey,
89
+ nonce,
90
+ Buffer.from(
91
+ box(
92
+ serialize([
93
+ data,
94
+ auth_token
95
+ ]),
96
+ nonce,
97
+ serverPublicKey,
98
+ pair.secretKey
99
+ )
178
100
  )
179
- ).toString('base64')}`,
101
+ ]),
180
102
  [pair.secretKey, pair.publicKey]
181
103
  ];
182
- }
104
+ };
183
105
 
184
- export const deserializeE2E = (data, serverPublicKey, clientPrivateKey) => {
185
- const [binaryNonce, binaryData] = data.split('.'),
106
+ export const deserializeE2E = async (data, serverPublicKey, clientPrivateKey) => {
107
+ const [binaryNonce, binaryData] = deserialize(data),
186
108
  baseArray = box.open(
187
- Buffer.from(binaryData, 'base64'),
188
- Buffer.from(binaryNonce, 'base64'),
189
- Buffer.from(serverPublicKey, 'base64'),
109
+ binaryData,
110
+ binaryNonce,
111
+ serverPublicKey,
190
112
  clientPrivateKey
191
113
  );
192
114
 
193
115
  if (!baseArray) throw 'Decrypting e2e message failed';
194
- return JSON.parse(Buffer.from(baseArray).toString('utf8'))[0];
195
- }
116
+ return deserialize(baseArray);
117
+ };
196
118
 
197
119
  export const encodeBinary = (s) => Buffer.from(s, 'utf8').toString('base64');
198
120
  export const decodeBinary = (s) => Buffer.from(s, 'base64').toString('utf8');