react-native-mosquito-transport 0.0.18 → 0.0.21

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.
Files changed (30) hide show
  1. package/.jshintignore +4 -0
  2. package/.jshintrc +16 -0
  3. package/README.md +75 -1
  4. package/TODO +10 -1
  5. package/example/ios/MosquitodbExample.xcodeproj/project.pbxproj +6 -5
  6. package/example/ios/MosquitodbExample.xcworkspace/contents.xcworkspacedata +10 -0
  7. package/example/ios/MosquitodbExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  8. package/example/ios/MosquitodbExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
  9. package/example/ios/MosquitodbExample.xcworkspace/xcuserdata/anthony.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  10. package/example/ios/MosquitodbExample.xcworkspace/xcuserdata/anthony.xcuserdatad/WorkspaceSettings.xcsettings +14 -0
  11. package/ios/Mosquitodb.swift +14 -1
  12. package/package.json +15 -14
  13. package/src/helpers/engine_api.js +39 -0
  14. package/src/helpers/peripherals.js +73 -127
  15. package/src/helpers/utils.js +48 -19
  16. package/src/helpers/values.js +8 -47
  17. package/src/helpers/variables.js +14 -6
  18. package/src/index.d.ts +103 -43
  19. package/src/index.js +198 -121
  20. package/src/products/auth/accessor.js +97 -36
  21. package/src/products/auth/index.js +151 -82
  22. package/src/products/database/accessor.js +720 -223
  23. package/src/products/database/bson.js +16 -0
  24. package/src/products/database/counter.js +16 -0
  25. package/src/products/database/index.js +303 -190
  26. package/src/products/database/types.js +1 -1
  27. package/src/products/database/validator.js +517 -254
  28. package/src/products/http_callable/index.js +111 -106
  29. package/src/products/storage/index.js +97 -88
  30. package/src/helpers/EngineApi.js +0 -33
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,75 @@
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
+ RNMosquitoTransport.initializeCache({
23
+ cachePassword: "****",
24
+ cacheProtocol: "sqlite",
25
+ });
26
+
27
+ const mclient = new RNMosquitoTransport({
28
+ projectUrl: "http://localhost:3444",
29
+ accessKey: "SERVER_ACCESS_KEY",
30
+ });
31
+ ```
32
+
33
+ ## Additional Documentations
34
+
35
+ - [RNMosquitoTransport Constructor](#RNMosquitoTransportConstructor)
36
+ - [dbName](#dbName)
37
+ - [dbUrl](#dbUrl)
38
+ - [projectUrl](#projectUrl)
39
+ - [disableCache](#disableCache)
40
+ - [accessKey](#accessKey)
41
+ - [maxRetries](#maxRetries)
42
+ - [enableE2E_Encryption](#enableE2E_Encryption)
43
+ - [serverE2E_PublicKey](#serverE2E_PublicKey)
44
+ - [extraHeaders](#extraHeaders)
45
+ - [castBSON](#castBSON)
46
+ - [RNMosquitoTransport Methods](#RNMosquitoTransportMethods)
47
+ - [initialCache](#initialCache)
48
+ - [getDatabase](#getDatabase)
49
+ - [collection](#collection)
50
+ - [auth](#auth)
51
+ - [storage](#storage)
52
+ - [fetchHttp](#fetchHttp)
53
+ - [listenReachableServer](#listenReachableServer)
54
+ - [getSocket](#getSocket)
55
+ - [batchWrite](#batchWrite)
56
+ - [TIMESTAMP](#TIMESTAMP)
57
+ - [AUTH_PROVIDER_ID](#AUTH_PROVIDER_ID)
58
+ - [DOCUMENT_EXTRACTION](#DOCUMENT_EXTRACTION)
59
+ - [GEO_JSON](#GEO_JSON)
60
+ - [FIND_GEO_JSON](#FIND_GEO_JSON)
61
+ - [DoNotEncrypt](#DoNotEncrypt)
62
+
63
+ ## RNMosquitoTransport Constructor
64
+
65
+ ### dbName
66
+
67
+
68
+ ### dbUrl
69
+
70
+
71
+ ### projectUrl
72
+
73
+ this is the base url of
74
+
75
+ ### disableCache
package/TODO CHANGED
@@ -1,4 +1,13 @@
1
1
  - fix local cache query on sqlite and fs
2
2
  - fix and add all mongodb query and update operator
3
3
  - reauthenticate
4
- - change `Object` in d.ts to [key: string]: any
4
+ - change `Object` in d.ts to [key: string]: any
5
+ - add `getServerTimeOffset` method
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`
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
@@ -354,7 +354,6 @@
354
354
  );
355
355
  name = "[CP] Copy Pods Resources";
356
356
  outputFileListPaths = (
357
- "${PODS_ROOT}/Target Support Files/Pods-MosquitodbExample/Pods-MosquitodbExample-resources-${CONFIGURATION}-output-files.xcfilelist",
358
357
  );
359
358
  runOnlyForDeploymentPostprocessing = 0;
360
359
  shellPath = /bin/sh;
@@ -501,7 +500,7 @@
501
500
  PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
502
501
  PRODUCT_NAME = MosquitodbExample;
503
502
  SWIFT_OPTIMIZATION_LEVEL = "-Onone";
504
- SWIFT_VERSION = 5.0;
503
+ SWIFT_VERSION = 5.3;
505
504
  VERSIONING_SYSTEM = "apple-generic";
506
505
  };
507
506
  name = Debug;
@@ -526,7 +525,7 @@
526
525
  );
527
526
  PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
528
527
  PRODUCT_NAME = MosquitodbExample;
529
- SWIFT_VERSION = 5.0;
528
+ SWIFT_VERSION = 5.3;
530
529
  VERSIONING_SYSTEM = "apple-generic";
531
530
  };
532
531
  name = Release;
@@ -564,7 +563,7 @@
564
563
  COPY_PHASE_STRIP = NO;
565
564
  ENABLE_STRICT_OBJC_MSGSEND = YES;
566
565
  ENABLE_TESTABILITY = YES;
567
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
566
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
568
567
  GCC_C_LANGUAGE_STANDARD = gnu99;
569
568
  GCC_DYNAMIC_NO_PIC = NO;
570
569
  GCC_NO_COMMON_BLOCKS = YES;
@@ -598,6 +597,7 @@
598
597
  "-DFOLLY_MOBILE=1",
599
598
  "-DFOLLY_USE_LIBCPP=1",
600
599
  );
600
+ REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
601
601
  SDKROOT = iphoneos;
602
602
  };
603
603
  name = Debug;
@@ -635,7 +635,7 @@
635
635
  COPY_PHASE_STRIP = YES;
636
636
  ENABLE_NS_ASSERTIONS = NO;
637
637
  ENABLE_STRICT_OBJC_MSGSEND = YES;
638
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
638
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
639
639
  GCC_C_LANGUAGE_STANDARD = gnu99;
640
640
  GCC_NO_COMMON_BLOCKS = YES;
641
641
  GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -661,6 +661,7 @@
661
661
  "-DFOLLY_MOBILE=1",
662
662
  "-DFOLLY_USE_LIBCPP=1",
663
663
  );
664
+ REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
664
665
  SDKROOT = iphoneos;
665
666
  VALIDATE_PRODUCT = YES;
666
667
  };
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ <FileRef
5
+ location = "group:MosquitodbExample.xcodeproj">
6
+ </FileRef>
7
+ <FileRef
8
+ location = "group:Pods/Pods.xcodeproj">
9
+ </FileRef>
10
+ </Workspace>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>PreviewsEnabled</key>
6
+ <false/>
7
+ </dict>
8
+ </plist>
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>BuildLocationStyle</key>
6
+ <string>UseAppPreferences</string>
7
+ <key>CustomBuildLocationType</key>
8
+ <string>RelativeToDerivedData</string>
9
+ <key>DerivedDataLocationStyle</key>
10
+ <string>Default</string>
11
+ <key>ShowSharedSchemesAutomaticallyEnabled</key>
12
+ <true/>
13
+ </dict>
14
+ </plist>
@@ -95,11 +95,18 @@ class MosquitodbUploadTask: NSObject, URLSessionDataDelegate {
95
95
 
96
96
  var request = URLRequest(url: URL(string: url)!)
97
97
  request.httpMethod = "POST"
98
+
99
+ if let extraHeaders = options["extraHeaders"] as? [[String: String]] {
100
+ for (key, value) in extraHeaders {
101
+ request.setValue(value, forHTTPHeaderField: key)
102
+ }
103
+ }
98
104
  request.setValue("application/json", forHTTPHeaderField: "Accept")
99
105
  request.setValue(authorization, forHTTPHeaderField: "Authorization")
100
106
  if options["authToken"] != nil {
101
107
  request.setValue(options["authToken"] as? String, forHTTPHeaderField: "Mosquito-Token")
102
108
  }
109
+ request.setValue(options["createHash"] as? String, forHTTPHeaderField: "hash-upload");
103
110
  request.setValue("buffer/upload", forHTTPHeaderField: "Content-Type")
104
111
  request.setValue(destination, forHTTPHeaderField: "Mosquito-Destination")
105
112
 
@@ -187,6 +194,12 @@ class MosquitodbDownloadTask: NSObject, URLSessionDownloadDelegate {
187
194
 
188
195
  var request = URLRequest(url: URL(string: url)!)
189
196
  request.httpMethod = "POST"
197
+
198
+ if let extraHeaders = options["extraHeaders"] as? [[String: String]] {
199
+ for (key, value) in extraHeaders {
200
+ request.setValue(value, forHTTPHeaderField: key)
201
+ }
202
+ }
190
203
  request.setValue(authorization, forHTTPHeaderField: "Authorization")
191
204
  if options["authToken"] != nil {
192
205
  request.setValue(options["authToken"] as? String, forHTTPHeaderField: "Mosquito-Token")
@@ -249,7 +262,7 @@ class MosquitodbDownloadTask: NSObject, URLSessionDownloadDelegate {
249
262
  "result": "{\"file\": \"\(dest)\"}"
250
263
  ]
251
264
  ])
252
- }else{
265
+ } else {
253
266
  let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
254
267
  let urlName = mainOptions["urlName"] as! String
255
268
  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.18",
4
- "description": "React native javascript sdk for mosquito-transport (https://github.com/deflexable/mosquito-transport)",
3
+ "version": "0.0.21",
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,28 +23,28 @@
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
33
  "crypto-js": "^4.2.0",
33
- "fast-json-stable-stringify": "^2.1.0",
34
- "guard-object": "^1.0.7",
35
- "json-buffer": "^3.0.1",
34
+ "entity-serializer": "^1.0.2",
35
+ "guard-object": "^1.1.3",
36
+ "lodash.clonedeep": "^4.5.0",
36
37
  "lodash.get": "^4.4.2",
37
- "lodash.isequal": "^4.5.0",
38
38
  "lodash.set": "^4.3.2",
39
39
  "lodash.unset": "^4.5.2",
40
40
  "react-native-get-random-values": "^1.9.0",
41
- "set-large-timeout": "^1.0.1",
41
+ "simplify-error": "^1.0.1",
42
42
  "socket.io-client": "^4.6.2",
43
43
  "subscription-listener": "^1.1.2",
44
44
  "tweetnacl": "^1.0.3"
45
45
  },
46
- "engines": {
47
- "node": ">= 16.0.0"
46
+ "peerDependencies": {
47
+ "react": "*",
48
+ "react-native": "*"
48
49
  }
49
50
  }
@@ -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,129 +3,44 @@ 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";
7
+ import { deserialize, serialize } from "entity-serializer";
6
8
 
7
9
  const { encrypt, decrypt } = aes_pkg;
8
10
  const { box, randomBytes } = naclPkg;
9
11
 
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
12
  export const listenReachableServer = (callback, projectUrl) => {
102
13
  let lastValue;
103
14
  return ServerReachableListener.listenTo(projectUrl, t => {
104
15
  if (typeof t === 'boolean' && t !== lastValue) callback?.(t);
105
16
  }, true);
106
- }
17
+ };
107
18
 
108
19
  export const prefixStoragePath = (path, prefix = 'file:///') => {
109
- if (!path) return path;
20
+ let cleanedPath = path.replace(/^[^/]+:\/{1,3}/, '');
110
21
 
111
- if (!path.startsWith('/') && !path.includes(':')) return prefix + path;
22
+ // Continuously remove any remaining protocol patterns until none are left
23
+ while (/^[^/]+:\/{1,3}/.test(cleanedPath)) {
24
+ cleanedPath = cleanedPath.replace(/^[^/]+:\/{1,3}/, '');
25
+ }
112
26
 
113
- return prefix + path.split('/').filter((v, i) => i && v).join('/');
114
- }
27
+ // Remove any leading slashes after protocol removal
28
+ cleanedPath = cleanedPath.replace(/^\/+/, '');
115
29
 
116
- export const getUrlExtension = (url) => {
117
- const r = url.split(/[#?]/)[0].split(".").pop().trim();
118
- return r === url ? '' : r;
119
- }
30
+ return `${prefix}${cleanedPath}`;
31
+ };
120
32
 
121
33
  export const niceTry = (promise) => new Promise(async resolve => {
122
-
123
34
  try {
124
35
  const r = await promise();
125
36
  resolve(r);
126
37
  } catch (e) { resolve(); }
127
38
  });
128
39
 
40
+ export const normalizeRoute = (route = '') => route.split('').map((v, i, a) =>
41
+ ((!i && v === '/') || (i === a.length - 1 && v === '/') || (i && a[i - 1] === '/' && v === '/')) ? '' : v
42
+ ).join('');
43
+
129
44
  export const shuffleArray = (n) => {
130
45
  const array = [...n];
131
46
  let currentIndex = array.length, randomIndex;
@@ -143,56 +58,87 @@ export const shuffleArray = (n) => {
143
58
  }
144
59
 
145
60
  export function sortArrayByObjectKey(arr = [], key) {
146
- return arr.slice(0).sort(function (a, b) {
61
+ return arr.sort(function (a, b) {
147
62
  const left = getLodash(a, key),
148
63
  right = getLodash(b, key);
149
64
 
150
65
  return (left > right) ? 1 : (left < right) ? -1 : 0;
151
66
  });
152
- }
67
+ };
68
+
69
+ export async function niceHash(str) {
70
+ try {
71
+ // Convert the string to a Uint8Array
72
+ const encoder = new TextEncoder();
73
+ const data = encoder.encode(str);
74
+
75
+ // Use the Web Crypto API to compute the hash
76
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
77
+
78
+ // Convert the ArrayBuffer to a hex string for readability
79
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
80
+ const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
81
+
82
+ // Convert to base64
83
+ return Buffer.from(hashHex, 'hex').toString('base64');
84
+ } catch (_) {
85
+ return str;
86
+ }
87
+ };
88
+
89
+ export const sameInstance = (var1, var2) => {
90
+ try {
91
+ return var1.constructor === var2.constructor &&
92
+ Object.getPrototypeOf(var1) === Object.getPrototypeOf(var2)
93
+ } catch (_) {
94
+ return false;
95
+ }
96
+ };
153
97
 
154
98
  export const encryptString = (txt, password, iv) => {
155
99
  return encrypt(txt, `${password || ''}${iv || ''}`).toString();
156
- }
100
+ };
157
101
 
158
102
  export const decryptString = (txt, password, iv) => {
159
103
  return decrypt(txt, `${password || ''}${iv || ''}`).toString(Utf8Encoder);
160
- }
104
+ };
161
105
 
162
- export const serializeE2E = (data, auth_token, serverPublicKey) => {
106
+ export const serializeE2E = async (data, auth_token, serverPublicKey) => {
163
107
  const pair = box.keyPair(),
164
- nonce = randomBytes(box.nonceLength),
165
- pubBase64 = Buffer.from(pair.publicKey).toString('base64'),
166
- nonceBase64 = Buffer.from(nonce).toString('base64');
108
+ nonce = randomBytes(box.nonceLength);
167
109
 
168
110
  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
111
+ serialize([
112
+ pair.publicKey,
113
+ nonce,
114
+ Buffer.from(
115
+ box(
116
+ serialize([
117
+ data,
118
+ auth_token
119
+ ]),
120
+ nonce,
121
+ serverPublicKey,
122
+ pair.secretKey
123
+ )
178
124
  )
179
- ).toString('base64')}`,
125
+ ]),
180
126
  [pair.secretKey, pair.publicKey]
181
127
  ];
182
- }
128
+ };
183
129
 
184
- export const deserializeE2E = (data, serverPublicKey, clientPrivateKey) => {
185
- const [binaryNonce, binaryData] = data.split('.'),
130
+ export const deserializeE2E = async (data, serverPublicKey, clientPrivateKey) => {
131
+ const [binaryNonce, binaryData] = deserialize(data),
186
132
  baseArray = box.open(
187
- Buffer.from(binaryData, 'base64'),
188
- Buffer.from(binaryNonce, 'base64'),
189
- Buffer.from(serverPublicKey, 'base64'),
133
+ binaryData,
134
+ binaryNonce,
135
+ serverPublicKey,
190
136
  clientPrivateKey
191
137
  );
192
138
 
193
139
  if (!baseArray) throw 'Decrypting e2e message failed';
194
- return JSON.parse(Buffer.from(baseArray).toString('utf8'))[0];
195
- }
140
+ return deserialize(baseArray);
141
+ };
196
142
 
197
143
  export const encodeBinary = (s) => Buffer.from(s, 'utf8').toString('base64');
198
144
  export const decodeBinary = (s) => Buffer.from(s, 'base64').toString('utf8');