react-native-mosquito-transport 0.0.14 → 0.0.16
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 +4 -0
- package/ios/Mosquitodb.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/package.json +8 -3
- package/src/helpers/EngineApi.js +0 -1
- package/src/helpers/utils.js +9 -5
- package/src/helpers/values.js +14 -4
- package/src/index.d.ts +87 -8
- package/src/index.js +52 -15
- package/src/products/auth/accessor.js +3 -23
- package/src/products/auth/index.js +12 -2
- package/src/products/database/accessor.js +4 -4
- package/src/products/database/index.js +5 -5
- package/src/products/database/validator.js +11 -4
package/TODO
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-mosquito-transport",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "React native javascript sdk for mosquito-transport (https://github.com/deflexable/mosquito-transport)",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,12 +31,17 @@
|
|
|
31
31
|
"@types/lodash": "^4.14.194",
|
|
32
32
|
"buffer": "^6.0.3",
|
|
33
33
|
"crypto-js": "^4.2.0",
|
|
34
|
+
"fast-json-stable-stringify": "^2.1.0",
|
|
35
|
+
"guard-object": "^1.0.6",
|
|
34
36
|
"json-buffer": "^3.0.1",
|
|
35
|
-
"lodash": "^4.
|
|
37
|
+
"lodash.get": "^4.4.2",
|
|
38
|
+
"lodash.isequal": "^4.5.0",
|
|
39
|
+
"lodash.set": "^4.3.2",
|
|
40
|
+
"lodash.unset": "^4.5.2",
|
|
36
41
|
"react-native-get-random-values": "^1.9.0",
|
|
37
42
|
"set-large-timeout": "^1.0.1",
|
|
38
43
|
"socket.io-client": "^4.6.2",
|
|
39
|
-
"subscription-listener": "^1.
|
|
44
|
+
"subscription-listener": "^1.1.2",
|
|
40
45
|
"tweetnacl": "^1.0.3"
|
|
41
46
|
},
|
|
42
47
|
"engines": {
|
package/src/helpers/EngineApi.js
CHANGED
|
@@ -14,7 +14,6 @@ const apis = {
|
|
|
14
14
|
_twitterSignin: (baseApi, ugly) => `${baseApi}/${ugly ? encodeBinary(apis._twitterSignin(baseApi)) : '_twitterSignin'}`,
|
|
15
15
|
_githubSignin: (baseApi, ugly) => `${baseApi}/${ugly ? encodeBinary(apis._githubSignin(baseApi)) : '_githubSignin'}`,
|
|
16
16
|
_signOut: (baseApi, ugly) => `${baseApi}/${ugly ? encodeBinary(apis._signOut(baseApi)) : '_signOut'}`,
|
|
17
|
-
_invalidateToken: (baseApi, ugly) => `${baseApi}/${ugly ? encodeBinary(apis._invalidateToken(baseApi)) : '_invalidateToken'}`,
|
|
18
17
|
_refreshAuthToken: (baseApi, ugly) => `${baseApi}/${ugly ? encodeBinary(apis._refreshAuthToken(baseApi)) : '_refreshAuthToken'}`,
|
|
19
18
|
_downloadFile: (baseApi, ugly) => `${baseApi}/${ugly ? encodeBinary(apis._downloadFile(baseApi)) : '_downloadFile'}`,
|
|
20
19
|
_uploadFile: (baseApi, ugly) => `${baseApi}/${ugly ? encodeBinary(apis._uploadFile(baseApi)) : '_uploadFile'}`,
|
package/src/helpers/utils.js
CHANGED
|
@@ -5,7 +5,7 @@ import { CacheStore, Scoped } from "./variables";
|
|
|
5
5
|
import { decryptString, encryptString, niceTry, serializeE2E } from "./peripherals";
|
|
6
6
|
|
|
7
7
|
export const updateCacheStore = () => {
|
|
8
|
-
const { cachePassword = DEFAULT_CACHE_PASSWORD, cacheProtocol = CACHE_PROTOCOL.ASYNC_STORAGE } = Scoped.ReleaseCacheData;
|
|
8
|
+
const { cachePassword = DEFAULT_CACHE_PASSWORD, cacheProtocol = CACHE_PROTOCOL.ASYNC_STORAGE, io } = Scoped.ReleaseCacheData;
|
|
9
9
|
|
|
10
10
|
clearTimeout(Scoped.cacheStorageReducer);
|
|
11
11
|
Scoped.cacheStorageReducer = setTimeout(() => {
|
|
@@ -15,7 +15,9 @@ export const updateCacheStore = () => {
|
|
|
15
15
|
cachePassword
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
if (
|
|
18
|
+
if (io) {
|
|
19
|
+
io.output(txt);
|
|
20
|
+
} else if (cacheProtocol === CACHE_PROTOCOL.ASYNC_STORAGE) {
|
|
19
21
|
AsyncStorage.setItem(CACHE_STORAGE_PATH, txt);
|
|
20
22
|
} else {
|
|
21
23
|
const fs = require('react-native-fs');
|
|
@@ -25,11 +27,13 @@ export const updateCacheStore = () => {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export const releaseCacheStore = async (builder) => {
|
|
28
|
-
const { cachePassword = DEFAULT_CACHE_PASSWORD, cacheProtocol = CACHE_PROTOCOL.ASYNC_STORAGE } = builder;
|
|
30
|
+
const { cachePassword = DEFAULT_CACHE_PASSWORD, cacheProtocol = CACHE_PROTOCOL.ASYNC_STORAGE, io } = builder;
|
|
29
31
|
|
|
30
32
|
let txt;
|
|
31
33
|
|
|
32
|
-
if (
|
|
34
|
+
if (io) {
|
|
35
|
+
txt = await io.input();
|
|
36
|
+
} else if (cacheProtocol === CACHE_PROTOCOL.ASYNC_STORAGE) {
|
|
33
37
|
txt = await niceTry(() => AsyncStorage.getItem(CACHE_STORAGE_PATH));
|
|
34
38
|
} else {
|
|
35
39
|
const fs = require('react-native-fs');
|
|
@@ -37,7 +41,7 @@ export const releaseCacheStore = async (builder) => {
|
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
const j = JSON.parse(decryptString(txt || '', cachePassword, cachePassword) || '{}');
|
|
40
|
-
|
|
44
|
+
|
|
41
45
|
Object.entries(j).forEach(([k, v]) => {
|
|
42
46
|
CacheStore[k] = v;
|
|
43
47
|
});
|
package/src/helpers/values.js
CHANGED
|
@@ -13,7 +13,8 @@ export const CACHE_STORAGE_PATH = encodeBinary('MOSQUITO_TRANSPORT_FREEZER'),
|
|
|
13
13
|
|
|
14
14
|
export const CACHE_PROTOCOL = {
|
|
15
15
|
ASYNC_STORAGE: 'async-storage',
|
|
16
|
-
REACT_NATIVE_FS: 'reat-native-fs'
|
|
16
|
+
REACT_NATIVE_FS: 'reat-native-fs',
|
|
17
|
+
SQLITE: 'sqlite' // TODO:
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
export const RETRIEVAL = {
|
|
@@ -43,8 +44,8 @@ export const WRITE_OPS = {
|
|
|
43
44
|
$MAX: '$max',
|
|
44
45
|
$MIN: '$min',
|
|
45
46
|
$MUL: '$mul',
|
|
46
|
-
$RENAME: '$rename'
|
|
47
|
-
|
|
47
|
+
$RENAME: '$rename',
|
|
48
|
+
$SET_ON_INSERT: '$setOnInsert'
|
|
48
49
|
};
|
|
49
50
|
export const WRITE_OPS_LIST = Object.values(WRITE_OPS);
|
|
50
51
|
|
|
@@ -69,4 +70,13 @@ export const READ_OPS_LIST = Object.values(READ_OPS);
|
|
|
69
70
|
|
|
70
71
|
export const Regexs = {
|
|
71
72
|
LINK: () => /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig
|
|
72
|
-
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const AUTH_PROVIDER_ID = {
|
|
76
|
+
GOOGLE: 'google.com',
|
|
77
|
+
FACEBOOK: 'facebook.com',
|
|
78
|
+
PASSWORD: 'password',
|
|
79
|
+
TWITTER: 'x.com',
|
|
80
|
+
GITHUB: 'github.com',
|
|
81
|
+
APPLE: 'apple.com'
|
|
82
|
+
};
|
package/src/index.d.ts
CHANGED
|
@@ -25,9 +25,63 @@ interface mtimestamp { $timestamp: 'now' }
|
|
|
25
25
|
export const TIMESTAMP: mtimestamp;
|
|
26
26
|
export function DOCUMENT_EXTRACTION(path: string): { $dynamicValue: number };
|
|
27
27
|
|
|
28
|
+
type longitude = number;
|
|
29
|
+
type latitude = number;
|
|
30
|
+
|
|
31
|
+
export function GEO_JSON(latitude: latitude, longitude: longitude): {
|
|
32
|
+
type: "Point",
|
|
33
|
+
coordinates: [longitude, latitude],
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function FIND_GEO_JSON(coordinates: [latitude, longitude], offSetMeters: number, centerMeters?: number): {
|
|
37
|
+
$near: {
|
|
38
|
+
$geometry: {
|
|
39
|
+
type: "Point",
|
|
40
|
+
coordinates: [longitude, latitude]
|
|
41
|
+
},
|
|
42
|
+
$minDistance: number | 0,
|
|
43
|
+
$maxDistance: number
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const AUTH_PROVIDER_ID: auth_provider_id;
|
|
48
|
+
|
|
49
|
+
interface auth_provider_id {
|
|
50
|
+
GOOGLE: 'google.com';
|
|
51
|
+
FACEBOOK: 'facebook.com';
|
|
52
|
+
PASSWORD: 'password';
|
|
53
|
+
TWITTER: 'x.com';
|
|
54
|
+
GITHUB: 'github.com';
|
|
55
|
+
APPLE: 'apple.com';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
type auth_provider_id_values = auth_provider_id['GOOGLE'] |
|
|
59
|
+
auth_provider_id['FACEBOOK'] |
|
|
60
|
+
auth_provider_id['PASSWORD'] |
|
|
61
|
+
auth_provider_id['GITHUB'] |
|
|
62
|
+
auth_provider_id['TWITTER'] |
|
|
63
|
+
auth_provider_id['APPLE'];
|
|
64
|
+
|
|
65
|
+
interface ReleaseCacheOption_IO {
|
|
66
|
+
/**
|
|
67
|
+
* This password will be used to encrypt data stored locally
|
|
68
|
+
*/
|
|
69
|
+
cachePassword?: string;
|
|
70
|
+
io: {
|
|
71
|
+
/**
|
|
72
|
+
* feeds mosquito-transport data
|
|
73
|
+
*/
|
|
74
|
+
input: () => string;
|
|
75
|
+
/**
|
|
76
|
+
* emits mosquito-transport internal data
|
|
77
|
+
*/
|
|
78
|
+
output: (data: string) => void;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
28
82
|
interface ReleaseCacheOption {
|
|
29
83
|
/**
|
|
30
|
-
* This password will be used to
|
|
84
|
+
* This password will be used to encrypt data stored locally
|
|
31
85
|
*/
|
|
32
86
|
cachePassword?: string;
|
|
33
87
|
/**
|
|
@@ -62,7 +116,7 @@ interface BatchWriteConfig extends WriteConfig {
|
|
|
62
116
|
|
|
63
117
|
export default class RNMT {
|
|
64
118
|
constructor(config: RNMTConfig);
|
|
65
|
-
static releaseCache(option?: ReleaseCacheOption): void;
|
|
119
|
+
static releaseCache(option?: ReleaseCacheOption | ReleaseCacheOption_IO): void;
|
|
66
120
|
getDatabase(dbName?: string, dbUrl?: string): GetDatabase;
|
|
67
121
|
collection(path: string): RNMTCollection;
|
|
68
122
|
auth(): RNMTAuth;
|
|
@@ -274,6 +328,7 @@ interface DocumentFind {
|
|
|
274
328
|
$or?: any[];
|
|
275
329
|
$text?: {
|
|
276
330
|
$search: string;
|
|
331
|
+
$field: string;
|
|
277
332
|
$language?: string;
|
|
278
333
|
$caseSensitive?: boolean;
|
|
279
334
|
$diacriticSensitive?: boolean;
|
|
@@ -303,8 +358,11 @@ interface RNMTAuth {
|
|
|
303
358
|
listenVerifiedStatus: (callback?: (verified?: boolean) => void, onError?: (error?: ErrorResponse) => void) => () => void;
|
|
304
359
|
listenAuthToken: (callback: (token: string) => void) => () => void;
|
|
305
360
|
getAuthToken: () => Promise<string>;
|
|
306
|
-
|
|
307
|
-
|
|
361
|
+
getRefreshToken: () => Promise<string>;
|
|
362
|
+
getRefreshTokenData: () => Promise<RefreshTokenData>;
|
|
363
|
+
parseToken: () => string;
|
|
364
|
+
listenAuth: (callback: (auth: TokenEventData) => void) => () => void;
|
|
365
|
+
getAuth: () => Promise<TokenEventData>;
|
|
308
366
|
signOut: () => Promise<void>;
|
|
309
367
|
forceRefreshToken: () => Promise<string>;
|
|
310
368
|
}
|
|
@@ -322,17 +380,38 @@ interface SignupResult extends SigninResult {
|
|
|
322
380
|
interface AuthData {
|
|
323
381
|
email?: string;
|
|
324
382
|
metadata: Object;
|
|
325
|
-
signupMethod:
|
|
326
|
-
currentAuthMethod:
|
|
383
|
+
signupMethod: auth_provider_id_values;
|
|
384
|
+
currentAuthMethod: auth_provider_id_values;
|
|
327
385
|
joinedOn: number;
|
|
328
|
-
encryptionKey: string;
|
|
329
386
|
uid: string;
|
|
330
387
|
claims: Object;
|
|
331
388
|
emailVerified: boolean;
|
|
389
|
+
tokenID: string;
|
|
390
|
+
disabled: boolean;
|
|
391
|
+
entityOf: string;
|
|
332
392
|
profile: {
|
|
333
393
|
photo: string;
|
|
334
394
|
name: string;
|
|
335
|
-
}
|
|
395
|
+
},
|
|
396
|
+
exp: number;
|
|
397
|
+
aud: string;
|
|
398
|
+
iss: string;
|
|
399
|
+
sub: string;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
interface RefreshTokenData {
|
|
403
|
+
uid: string;
|
|
404
|
+
tokenID: string;
|
|
405
|
+
isRefreshToken: true;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
interface TokenEventData extends AuthData {
|
|
409
|
+
tokenManager: TokenManager | null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
interface TokenManager {
|
|
413
|
+
refreshToken: string;
|
|
414
|
+
accessToken: string;
|
|
336
415
|
}
|
|
337
416
|
|
|
338
417
|
interface RNMTStorage {
|
package/src/index.js
CHANGED
|
@@ -6,12 +6,12 @@ import { MTAuth } from "./products/auth";
|
|
|
6
6
|
import { MTCollection, batchWrite } from "./products/database";
|
|
7
7
|
import { MTStorage } from "./products/storage";
|
|
8
8
|
import { ServerReachableListener, TokenRefreshListener } from "./helpers/listeners";
|
|
9
|
-
import { initTokenRefresher, listenTokenReady, triggerAuthToken } from "./products/auth/accessor";
|
|
9
|
+
import { initTokenRefresher, listenToken, listenTokenReady, parseToken, triggerAuthToken } from "./products/auth/accessor";
|
|
10
10
|
import { TIMESTAMP, DOCUMENT_EXTRACTION, FIND_GEO_JSON, GEO_JSON } from "./products/database/types";
|
|
11
11
|
import { mfetch } from "./products/http_callable";
|
|
12
12
|
import { io } from "socket.io-client";
|
|
13
13
|
import { validateCollectionPath } from "./products/database/validator";
|
|
14
|
-
import { CACHE_PROTOCOL, Regexs } from "./helpers/values";
|
|
14
|
+
import { AUTH_PROVIDER_ID, CACHE_PROTOCOL, Regexs } from "./helpers/values";
|
|
15
15
|
import { trySendPendingWrite } from "./products/database/accessor";
|
|
16
16
|
import EngineApi from './helpers/EngineApi';
|
|
17
17
|
import { parse, stringify } from 'json-buffer';
|
|
@@ -35,7 +35,9 @@ class RNMT {
|
|
|
35
35
|
};
|
|
36
36
|
const { projectUrl } = this.config;
|
|
37
37
|
|
|
38
|
+
this.config.secureUrl = projectUrl.startsWith('https');
|
|
38
39
|
this.config.baseUrl = projectUrl.split('://')[1];
|
|
40
|
+
this.config.wsPrefix = this.config.secureUrl ? 'wss' : 'ws';
|
|
39
41
|
|
|
40
42
|
if (!Scoped.ReleaseCacheData)
|
|
41
43
|
throw `releaseCache must be called before creating any ${this.constructor.name} instance`;
|
|
@@ -46,16 +48,41 @@ class RNMT {
|
|
|
46
48
|
triggerAuthToken(projectUrl);
|
|
47
49
|
initTokenRefresher({ ...this.config }, true);
|
|
48
50
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
});
|
|
51
|
+
const disconnectionGlich = {};
|
|
52
|
+
let socket, lastUid, lastSocketProcess = 0, hasInited;
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
listenToken((token, thisInited) => {
|
|
55
|
+
const user = token && parseToken(token);
|
|
56
|
+
|
|
57
|
+
const thisUid = (user?.uid || null);
|
|
58
|
+
if (lastUid === thisUid && (hasInited || !thisInited)) return;
|
|
59
|
+
if (!hasInited) hasInited = thisInited;
|
|
60
|
+
lastUid = thisUid;
|
|
61
|
+
|
|
62
|
+
if (lastSocketProcess) disconnectionGlich[lastSocketProcess] = true;
|
|
63
|
+
socket.close();
|
|
64
|
+
|
|
65
|
+
const thisProcess = ++lastSocketProcess;
|
|
66
|
+
socket = io(`${this.config.wsPrefix}://${projectUrl.split('://')[1]}`, {
|
|
67
|
+
auth: {
|
|
68
|
+
_m_internal: true,
|
|
69
|
+
_from_base: true,
|
|
70
|
+
atoken: token
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
socket.on('_signal_signout', () => {
|
|
75
|
+
this.auth().signOut();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
socket.on('connect', () => {
|
|
79
|
+
ServerReachableListener.dispatch(projectUrl, true);
|
|
80
|
+
});
|
|
81
|
+
socket.on('disconnect', () => {
|
|
82
|
+
if (!disconnectionGlich[thisProcess])
|
|
83
|
+
ServerReachableListener.dispatch(projectUrl, false);
|
|
84
|
+
});
|
|
85
|
+
}, projectUrl);
|
|
59
86
|
|
|
60
87
|
listenReachableServer(c => {
|
|
61
88
|
Scoped.IS_CONNECTED[projectUrl] = c;
|
|
@@ -69,7 +96,7 @@ class RNMT {
|
|
|
69
96
|
}
|
|
70
97
|
|
|
71
98
|
static releaseCache(prop) {
|
|
72
|
-
if (Scoped.ReleaseCacheData) throw `calling ${this.name} multiple times is prohibited`;
|
|
99
|
+
if (Scoped.ReleaseCacheData) throw `calling ${this.name}() multiple times is prohibited`;
|
|
73
100
|
validateReleaseCacheProp({ ...prop });
|
|
74
101
|
Scoped.ReleaseCacheData = { ...prop };
|
|
75
102
|
releaseCacheStore({ ...prop });
|
|
@@ -95,7 +122,7 @@ class RNMT {
|
|
|
95
122
|
|
|
96
123
|
getSocket = (configOpts) => {
|
|
97
124
|
const { disableAuth, authHandshake } = configOpts || {},
|
|
98
|
-
{ projectUrl, uglify, accessKey, serverE2E_PublicKey } = this.config;
|
|
125
|
+
{ projectUrl, uglify, accessKey, serverE2E_PublicKey, wsPrefix } = this.config;
|
|
99
126
|
|
|
100
127
|
const restrictedRoute = [
|
|
101
128
|
_listenCollection,
|
|
@@ -194,7 +221,7 @@ class RNMT {
|
|
|
194
221
|
const mtoken = disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl];
|
|
195
222
|
const [reqBuilder, [privateKey]] = uglify ? serializeE2E({ accessKey, a_extras: authHandshake }, mtoken, serverE2E_PublicKey) : [null, []];
|
|
196
223
|
|
|
197
|
-
socket = io(
|
|
224
|
+
socket = io(`${wsPrefix}://${projectUrl.split('://')[1]}`, {
|
|
198
225
|
auth: uglify ? {
|
|
199
226
|
ugly: true,
|
|
200
227
|
e2e: reqBuilder
|
|
@@ -299,8 +326,17 @@ const validateReleaseCacheProp = (prop) => {
|
|
|
299
326
|
throw `Invalid value supplied to cachePassword, value must be a string and greater than 0 characters`;
|
|
300
327
|
} else if (k === 'cacheProtocol') {
|
|
301
328
|
if (!cacheList.includes(`${v}`)) throw `unknown value supplied to ${k}, expected any of ${cacheList}`;
|
|
329
|
+
} else if (k === 'io') {
|
|
330
|
+
Object.entries(v).forEach(([k, v]) => {
|
|
331
|
+
if (k === 'input' || k === 'output') {
|
|
332
|
+
if (typeof v !== 'function')
|
|
333
|
+
throw `Invalid value supplied to "io.${k}", expected a function but got "${v}"`;
|
|
334
|
+
} else throw `Unexpected property named "io.${k}"`;
|
|
335
|
+
});
|
|
302
336
|
} else throw `Unexpected property named ${k}`;
|
|
303
337
|
});
|
|
338
|
+
|
|
339
|
+
if (!prop?.io && !prop?.cacheProtocol) throw 'You need to provide either "io" or "cacheProtocol"';
|
|
304
340
|
}
|
|
305
341
|
|
|
306
342
|
const validator = {
|
|
@@ -363,7 +399,8 @@ export {
|
|
|
363
399
|
TIMESTAMP,
|
|
364
400
|
DOCUMENT_EXTRACTION,
|
|
365
401
|
FIND_GEO_JSON,
|
|
366
|
-
GEO_JSON
|
|
402
|
+
GEO_JSON,
|
|
403
|
+
AUTH_PROVIDER_ID
|
|
367
404
|
};
|
|
368
405
|
|
|
369
406
|
export default RNMT;
|
|
@@ -2,8 +2,8 @@ import setLargeTimeout from "set-large-timeout";
|
|
|
2
2
|
import { doSignOut } from ".";
|
|
3
3
|
import EngineApi from "../../helpers/EngineApi";
|
|
4
4
|
import { AuthTokenListener, TokenRefreshListener } from "../../helpers/listeners";
|
|
5
|
-
import { decodeBinary, deserializeE2E, listenReachableServer
|
|
6
|
-
import {
|
|
5
|
+
import { decodeBinary, deserializeE2E, listenReachableServer } from "../../helpers/peripherals";
|
|
6
|
+
import { awaitStore, buildFetchInterface, simplifyError, updateCacheStore } from "../../helpers/utils";
|
|
7
7
|
import { CacheStore, Scoped } from "../../helpers/variables";
|
|
8
8
|
|
|
9
9
|
export const listenToken = (callback, projectUrl) =>
|
|
@@ -103,7 +103,6 @@ const refreshToken = (builder, processRef, remainRetries = 7, initialRetries = 7
|
|
|
103
103
|
if (isForceRefresh) Scoped.InitiatedForcedToken[projectUrl] = true;
|
|
104
104
|
updateCacheStore();
|
|
105
105
|
initTokenRefresher(builder);
|
|
106
|
-
invalidateToken(builder, token);
|
|
107
106
|
} else reject(lostProcess.simpleError);
|
|
108
107
|
} catch (e) {
|
|
109
108
|
if (e.simpleError) {
|
|
@@ -129,23 +128,4 @@ const refreshToken = (builder, processRef, remainRetries = 7, initialRetries = 7
|
|
|
129
128
|
}, projectUrl);
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
export const invalidateToken = async (builder, token) => {
|
|
135
|
-
try {
|
|
136
|
-
const { projectUrl, accessKey, uglify, serverE2E_PublicKey } = builder;
|
|
137
|
-
await awaitReachableServer(projectUrl);
|
|
138
|
-
|
|
139
|
-
const [reqBuilder] = buildFetchInterface({
|
|
140
|
-
body: { token },
|
|
141
|
-
accessKey,
|
|
142
|
-
uglify,
|
|
143
|
-
serverE2E_PublicKey
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
const r = await (await fetch(EngineApi._invalidateToken(projectUrl, uglify), reqBuilder)).json();
|
|
147
|
-
if (r.simpleError) throw r;
|
|
148
|
-
} catch (e) {
|
|
149
|
-
throw simplifyCaughtError(e).simpleError;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
131
|
+
});
|
|
@@ -42,7 +42,7 @@ export class MTAuth {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
listenVerifiedStatus(callback, onError) {
|
|
45
|
-
const { projectUrl, serverE2E_PublicKey, uglify, baseUrl } = this.builder;
|
|
45
|
+
const { projectUrl, serverE2E_PublicKey, uglify, baseUrl, wsPrefix } = this.builder;
|
|
46
46
|
|
|
47
47
|
let socket, wasDisconnected, lastToken = Scoped.AuthJWTToken[projectUrl] || null, lastInitRef = 0;
|
|
48
48
|
|
|
@@ -58,7 +58,7 @@ export class MTAuth {
|
|
|
58
58
|
const mtoken = Scoped.AuthJWTToken[projectUrl],
|
|
59
59
|
[reqBuilder, [privateKey]] = uglify ? serializeE2E({ mtoken }, undefined, serverE2E_PublicKey) : [null, []];
|
|
60
60
|
|
|
61
|
-
socket = io(
|
|
61
|
+
socket = io(`${wsPrefix}://${baseUrl}`, {
|
|
62
62
|
auth: uglify ? {
|
|
63
63
|
e2e: reqBuilder,
|
|
64
64
|
_m_internal: true
|
|
@@ -104,6 +104,13 @@ export class MTAuth {
|
|
|
104
104
|
|
|
105
105
|
listenAuthToken = (callback) => listenToken(callback, this.builder.projectUrl);
|
|
106
106
|
|
|
107
|
+
getRefreshToken = async () => {
|
|
108
|
+
await awaitStore();
|
|
109
|
+
return CacheStore.AuthStore[this.builder.projectUrl]?.refreshToken;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
parseToken = (token) => parseToken(token);
|
|
113
|
+
|
|
107
114
|
getAuthToken = () => new Promise(resolve => {
|
|
108
115
|
const l = listenToken(t => {
|
|
109
116
|
l();
|
|
@@ -111,6 +118,9 @@ export class MTAuth {
|
|
|
111
118
|
}, this.builder.projectUrl);
|
|
112
119
|
});
|
|
113
120
|
|
|
121
|
+
/**
|
|
122
|
+
* @type {import('../../index').RNMTAuth['listenAuth']}
|
|
123
|
+
*/
|
|
114
124
|
listenAuth = (callback) => {
|
|
115
125
|
let lastTrig;
|
|
116
126
|
|
|
@@ -2,10 +2,10 @@ import { IS_RAW_OBJECT, objToUniqueString, queryEntries, shuffleArray, sortArray
|
|
|
2
2
|
import { awaitStore, updateCacheStore } from "../../helpers/utils";
|
|
3
3
|
import { CacheStore } from "../../helpers/variables";
|
|
4
4
|
import { confirmFilterDoc } from "./validator";
|
|
5
|
-
import getLodash from 'lodash
|
|
6
|
-
import setLodash from 'lodash
|
|
7
|
-
import unsetLodash from 'lodash
|
|
8
|
-
import isEqual from 'lodash
|
|
5
|
+
import getLodash from 'lodash.get';
|
|
6
|
+
import setLodash from 'lodash.set';
|
|
7
|
+
import unsetLodash from 'lodash.unset';
|
|
8
|
+
import isEqual from 'lodash.isequal';
|
|
9
9
|
import { DEFAULT_DB_NAME, DEFAULT_DB_URL, DELIVERY, RETRIEVAL, WRITE_OPS, WRITE_OPS_LIST } from "../../helpers/values";
|
|
10
10
|
import { DatabaseRecordsListener } from "../../helpers/listeners";
|
|
11
11
|
|
|
@@ -8,7 +8,7 @@ import { addPendingWrites, generateRecordID, getRecord, insertRecord, listenQuer
|
|
|
8
8
|
import { validateCollectionPath, validateFilter, validateReadConfig, validateWriteValue } from "./validator";
|
|
9
9
|
import { awaitRefreshToken, listenToken } from "../auth/accessor";
|
|
10
10
|
import { DEFAULT_DB_NAME, DEFAULT_DB_URL, DELIVERY, RETRIEVAL } from "../../helpers/values";
|
|
11
|
-
import setLodash from 'lodash
|
|
11
|
+
import setLodash from 'lodash.set';
|
|
12
12
|
|
|
13
13
|
export class MTCollection {
|
|
14
14
|
constructor(config) {
|
|
@@ -111,7 +111,7 @@ const {
|
|
|
111
111
|
} = EngineApi;
|
|
112
112
|
|
|
113
113
|
const listenDocument = (callback, onError, builder, config) => {
|
|
114
|
-
const { projectUrl, serverE2E_PublicKey, baseUrl, dbUrl, dbName, accessKey, path, disableCache, command, uglify } = builder,
|
|
114
|
+
const { projectUrl, wsPrefix, serverE2E_PublicKey, baseUrl, dbUrl, dbName, accessKey, path, disableCache, command, uglify } = builder,
|
|
115
115
|
{ find, findOne, sort, direction, limit } = command,
|
|
116
116
|
{ disableAuth } = config || {},
|
|
117
117
|
accessId = generateRecordID(builder, config),
|
|
@@ -163,7 +163,7 @@ const listenDocument = (callback, onError, builder, config) => {
|
|
|
163
163
|
|
|
164
164
|
const [encPlate, [privateKey]] = uglify ? serializeE2E({ accessKey, _body: authObj }, mtoken, serverE2E_PublicKey) : ['', []];
|
|
165
165
|
|
|
166
|
-
socket = io(
|
|
166
|
+
socket = io(`${wsPrefix}://${baseUrl}`, {
|
|
167
167
|
auth: uglify ? { e2e: encPlate, _m_internal: true } : {
|
|
168
168
|
accessKey,
|
|
169
169
|
_body: authObj,
|
|
@@ -217,7 +217,7 @@ const listenDocument = (callback, onError, builder, config) => {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
const initOnDisconnectionTask = (builder, value, type) => {
|
|
220
|
-
const { projectUrl, baseUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, path, command, uglify } = builder,
|
|
220
|
+
const { projectUrl, wsPrefix, baseUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, path, command, uglify } = builder,
|
|
221
221
|
{ find } = command || {},
|
|
222
222
|
disableAuth = false;
|
|
223
223
|
|
|
@@ -240,7 +240,7 @@ const initOnDisconnectionTask = (builder, value, type) => {
|
|
|
240
240
|
dbUrl
|
|
241
241
|
};
|
|
242
242
|
|
|
243
|
-
socket = io(
|
|
243
|
+
socket = io(`${wsPrefix}://${baseUrl}`, {
|
|
244
244
|
auth: uglify ? {
|
|
245
245
|
e2e: serializeE2E(authObj, mtoken, serverE2E_PublicKey)[0],
|
|
246
246
|
_m_internal: true
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IS_DECIMAL_NUMBER, IS_RAW_OBJECT, IS_WHOLE_NUMBER, queryEntries } from "../../helpers/peripherals";
|
|
2
2
|
import { READ_OPS, READ_OPS_LIST, RETRIEVAL } from "../../helpers/values";
|
|
3
|
-
import getLodash from 'lodash
|
|
4
|
-
import isEqual from 'lodash
|
|
3
|
+
import getLodash from 'lodash.get';
|
|
4
|
+
import isEqual from 'lodash.isequal';
|
|
5
5
|
|
|
6
6
|
const dirn = ['desc', 'asc', 'ascending', 'descending'];
|
|
7
7
|
|
|
@@ -202,12 +202,19 @@ const evaluateFilter = (data = {}, filter = {}) => {
|
|
|
202
202
|
} else logics.push(false);
|
|
203
203
|
} else if ($ === $TEXT) {
|
|
204
204
|
if (commandSplit.slice(-1)[0].$ === '$search') {
|
|
205
|
-
const { $caseSensitive, $
|
|
205
|
+
const { $caseSensitive, $search, $field } = filter.$text;
|
|
206
206
|
|
|
207
207
|
if (typeof value !== 'string' || typeof $search !== 'string')
|
|
208
208
|
throw `$search must have a string value`;
|
|
209
|
+
if (!$field) throw '"$field" is required inside "$text" operator when "disableCache=false"';
|
|
210
|
+
const fieldArr = Array.isArray($field) ? $field : [$field];
|
|
209
211
|
|
|
210
|
-
|
|
212
|
+
fieldArr.forEach(v => {
|
|
213
|
+
if (typeof v !== 'string' || !v.trim())
|
|
214
|
+
throw `invalid item inside "$field", expected a non-empty string but got "${v}"`;
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const searchTxt = fieldArr.map(v => getLodash(dataObj, v || '')).map(v =>
|
|
211
218
|
`${typeof v === 'string' ? v :
|
|
212
219
|
Array.isArray(v) ? v.map(v => typeof v === 'string' ? v : '').join(' ').trim() : ''}`.trim()
|
|
213
220
|
).join(' ').trim();
|