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.
- package/.jshintignore +4 -0
- package/.jshintrc +16 -0
- package/README.md +75 -1
- package/TODO +10 -1
- package/example/ios/MosquitodbExample.xcodeproj/project.pbxproj +6 -5
- package/example/ios/MosquitodbExample.xcworkspace/contents.xcworkspacedata +10 -0
- package/example/ios/MosquitodbExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/example/ios/MosquitodbExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
- package/example/ios/MosquitodbExample.xcworkspace/xcuserdata/anthony.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/MosquitodbExample.xcworkspace/xcuserdata/anthony.xcuserdatad/WorkspaceSettings.xcsettings +14 -0
- package/ios/Mosquitodb.swift +14 -1
- package/package.json +15 -14
- package/src/helpers/engine_api.js +39 -0
- package/src/helpers/peripherals.js +73 -127
- package/src/helpers/utils.js +48 -19
- package/src/helpers/values.js +8 -47
- package/src/helpers/variables.js +14 -6
- package/src/index.d.ts +103 -43
- package/src/index.js +198 -121
- package/src/products/auth/accessor.js +97 -36
- package/src/products/auth/index.js +151 -82
- package/src/products/database/accessor.js +720 -223
- package/src/products/database/bson.js +16 -0
- package/src/products/database/counter.js +16 -0
- package/src/products/database/index.js +303 -190
- package/src/products/database/types.js +1 -1
- package/src/products/database/validator.js +517 -254
- package/src/products/http_callable/index.js +111 -106
- package/src/products/storage/index.js +97 -88
- package/src/helpers/EngineApi.js +0 -33
package/src/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import 'react-native-get-random-values';
|
|
2
|
-
import {
|
|
3
|
-
import { releaseCacheStore } from "./helpers/utils";
|
|
4
|
-
import { Scoped } from "./helpers/variables";
|
|
5
|
-
import {
|
|
6
|
-
import { MTCollection, batchWrite } from "./products/database";
|
|
2
|
+
import { deserializeE2E, listenReachableServer, serializeE2E } from "./helpers/peripherals";
|
|
3
|
+
import { awaitStore, releaseCacheStore } from "./helpers/utils";
|
|
4
|
+
import { CacheStore, Scoped } from "./helpers/variables";
|
|
5
|
+
import { MTCollection, batchWrite, trySendPendingWrite } from "./products/database";
|
|
7
6
|
import { MTStorage } from "./products/storage";
|
|
8
7
|
import { ServerReachableListener, TokenRefreshListener } from "./helpers/listeners";
|
|
9
|
-
import { initTokenRefresher, listenToken, listenTokenReady,
|
|
8
|
+
import { initTokenRefresher, listenToken, listenTokenReady, triggerAuthToken } from "./products/auth/accessor";
|
|
10
9
|
import { TIMESTAMP, DOCUMENT_EXTRACTION, FIND_GEO_JSON, GEO_JSON } from "./products/database/types";
|
|
11
10
|
import { mfetch } from "./products/http_callable";
|
|
12
11
|
import { io } from "socket.io-client";
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
12
|
+
import { AUTH_PROVIDER_ID, CACHE_PROTOCOL } from "./helpers/values";
|
|
13
|
+
import EngineApi from './helpers/engine_api';
|
|
14
|
+
import { Validator } from 'guard-object';
|
|
15
|
+
import cloneDeep from 'lodash.clonedeep';
|
|
16
|
+
import { Buffer } from 'buffer';
|
|
17
|
+
import MTAuth, { purgePendingToken } from './products/auth';
|
|
18
18
|
|
|
19
19
|
const {
|
|
20
20
|
_listenCollection,
|
|
@@ -24,69 +24,86 @@ const {
|
|
|
24
24
|
_listenUserVerification
|
|
25
25
|
} = EngineApi;
|
|
26
26
|
|
|
27
|
+
// https://socket.io/docs/v3/emit-cheatsheet/#reserved-events
|
|
28
|
+
const reservedEventName = [
|
|
29
|
+
'connect',
|
|
30
|
+
'connect_error',
|
|
31
|
+
'disconnect',
|
|
32
|
+
'disconnecting',
|
|
33
|
+
'newListener',
|
|
34
|
+
'removeListener'
|
|
35
|
+
];
|
|
36
|
+
|
|
27
37
|
class RNMT {
|
|
28
38
|
constructor(config) {
|
|
29
39
|
validateMTConfig(config, this);
|
|
30
40
|
this.config = {
|
|
31
41
|
...config,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
serverE2E_PublicKey: config.serverE2E_PublicKey && new Uint8Array(Buffer.from(config.serverE2E_PublicKey, 'base64')),
|
|
43
|
+
castBSON: config.castBSON === undefined || config.castBSON,
|
|
44
|
+
maxRetries: config.maxRetries || 3,
|
|
45
|
+
uglify: config.enableE2E_Encryption
|
|
35
46
|
};
|
|
36
|
-
const { projectUrl } = this.config;
|
|
47
|
+
const { projectUrl, extraHeaders } = this.config;
|
|
37
48
|
|
|
38
49
|
this.config.secureUrl = projectUrl.startsWith('https');
|
|
39
50
|
this.config.baseUrl = projectUrl.split('://')[1];
|
|
40
51
|
this.config.wsPrefix = this.config.secureUrl ? 'wss' : 'ws';
|
|
41
52
|
|
|
42
53
|
if (!Scoped.ReleaseCacheData)
|
|
43
|
-
throw `
|
|
54
|
+
throw `initializeCache must be called before creating any ${this.constructor.name} instance`;
|
|
44
55
|
|
|
45
56
|
if (!Scoped.InitializedProject[projectUrl]) {
|
|
46
|
-
Scoped.InitializedProject[projectUrl] =
|
|
57
|
+
Scoped.InitializedProject[projectUrl] = cloneDeep(this.config);
|
|
47
58
|
Scoped.LastTokenRefreshRef[projectUrl] = 0;
|
|
48
59
|
triggerAuthToken(projectUrl);
|
|
49
60
|
initTokenRefresher({ ...this.config }, true);
|
|
50
61
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
listenToken((token, thisInited) => {
|
|
55
|
-
const user = token && parseToken(token);
|
|
62
|
+
let isConnected,
|
|
63
|
+
lastSentToken,
|
|
64
|
+
queuedToken;
|
|
56
65
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
const socket = io(`${this.config.wsPrefix}://${this.config.baseUrl}`, {
|
|
67
|
+
transports: ['websocket', 'polling', 'flashsocket'],
|
|
68
|
+
extraHeaders,
|
|
69
|
+
auth: {
|
|
70
|
+
_m_internal: true,
|
|
71
|
+
_from_base: true
|
|
72
|
+
}
|
|
73
|
+
});
|
|
61
74
|
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
socket.on('_signal_signout', () => {
|
|
76
|
+
this.auth().signOut();
|
|
77
|
+
});
|
|
64
78
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
socket.on('connect', () => {
|
|
80
|
+
isConnected = true;
|
|
81
|
+
Scoped.IS_CONNECTED[projectUrl] = true;
|
|
82
|
+
if (queuedToken) updateMountedToken(queuedToken.token);
|
|
83
|
+
ServerReachableListener.dispatch(projectUrl, true);
|
|
84
|
+
awaitStore().then(() => {
|
|
85
|
+
trySendPendingWrite(projectUrl);
|
|
72
86
|
});
|
|
87
|
+
});
|
|
73
88
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
socket.on('disconnect', () => {
|
|
90
|
+
isConnected = false;
|
|
91
|
+
Scoped.IS_CONNECTED[projectUrl] = false;
|
|
92
|
+
ServerReachableListener.dispatch(projectUrl, false);
|
|
93
|
+
});
|
|
77
94
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}, projectUrl);
|
|
95
|
+
const updateMountedToken = (token) => {
|
|
96
|
+
if ((lastSentToken || null) !== (token || null)) {
|
|
97
|
+
socket.emit('_update_mounted_user', token || null);
|
|
98
|
+
lastSentToken = token;
|
|
99
|
+
}
|
|
100
|
+
queuedToken = undefined;
|
|
101
|
+
};
|
|
86
102
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
103
|
+
listenToken(token => {
|
|
104
|
+
if (isConnected) {
|
|
105
|
+
updateMountedToken(token);
|
|
106
|
+
} else queuedToken = { token };
|
|
90
107
|
}, projectUrl);
|
|
91
108
|
|
|
92
109
|
TokenRefreshListener.listenTo(projectUrl, v => {
|
|
@@ -95,25 +112,29 @@ class RNMT {
|
|
|
95
112
|
}
|
|
96
113
|
}
|
|
97
114
|
|
|
98
|
-
static
|
|
115
|
+
static initializeCache(prop) {
|
|
99
116
|
if (Scoped.ReleaseCacheData) throw `calling ${this.name}() multiple times is prohibited`;
|
|
100
117
|
validateReleaseCacheProp({ ...prop });
|
|
101
118
|
Scoped.ReleaseCacheData = { ...prop };
|
|
102
119
|
releaseCacheStore({ ...prop });
|
|
120
|
+
// purge residue tokens
|
|
121
|
+
awaitStore().then(() => {
|
|
122
|
+
Object.keys(CacheStore.PendingAuthPurge).forEach(k => {
|
|
123
|
+
purgePendingToken(k);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
103
126
|
}
|
|
104
127
|
|
|
105
128
|
getDatabase = (dbName, dbUrl) => ({
|
|
106
129
|
collection: (path) => new MTCollection({
|
|
107
130
|
...this.config,
|
|
108
131
|
path,
|
|
109
|
-
...
|
|
110
|
-
...
|
|
132
|
+
...dbName ? { dbName } : {},
|
|
133
|
+
...dbUrl ? { dbUrl } : {}
|
|
111
134
|
})
|
|
112
135
|
});
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return new MTCollection({ ...this.config, path });
|
|
116
|
-
}
|
|
136
|
+
|
|
137
|
+
collection = (path) => new MTCollection({ ...this.config, path });
|
|
117
138
|
batchWrite = (map, configx) => batchWrite({ ...this.config }, map, configx);
|
|
118
139
|
auth = () => new MTAuth({ ...this.config });
|
|
119
140
|
storage = () => new MTStorage({ ...this.config });
|
|
@@ -121,8 +142,8 @@ class RNMT {
|
|
|
121
142
|
listenReachableServer = (callback) => listenReachableServer(callback, this.config.projectUrl);
|
|
122
143
|
|
|
123
144
|
getSocket = (configOpts) => {
|
|
124
|
-
const { disableAuth, authHandshake } = configOpts || {}
|
|
125
|
-
|
|
145
|
+
const { disableAuth, authHandshake } = configOpts || {};
|
|
146
|
+
const { projectUrl, uglify, accessKey, serverE2E_PublicKey, wsPrefix, extraHeaders } = this.config;
|
|
126
147
|
|
|
127
148
|
const restrictedRoute = [
|
|
128
149
|
_listenCollection,
|
|
@@ -130,12 +151,14 @@ class RNMT {
|
|
|
130
151
|
_startDisconnectWriteTask,
|
|
131
152
|
_cancelDisconnectWriteTask,
|
|
132
153
|
_listenUserVerification
|
|
133
|
-
];
|
|
154
|
+
].map(v => [v(), v(true)]).flat();
|
|
134
155
|
|
|
135
|
-
|
|
136
|
-
|
|
156
|
+
const makeSocketCallback = () =>
|
|
157
|
+
new Promise(resolve => {
|
|
137
158
|
socketReadyCallback = resolve;
|
|
138
|
-
})
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
let socketReadyCallback,
|
|
139
162
|
socketReadyPromise = makeSocketCallback(),
|
|
140
163
|
socketListenerList = [],
|
|
141
164
|
socketListenerIte = 0;
|
|
@@ -145,25 +168,31 @@ class RNMT {
|
|
|
145
168
|
tokenListener,
|
|
146
169
|
clientPrivateKey;
|
|
147
170
|
|
|
148
|
-
const listenerCallback = (callback) => function () {
|
|
149
|
-
|
|
171
|
+
const listenerCallback = (route, callback) => async function () {
|
|
172
|
+
if (reservedEventName.includes(route)) {
|
|
173
|
+
callback?.(...[...arguments]);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const [[args, not_encrypted], emitable] = [...arguments];
|
|
150
178
|
let res;
|
|
151
179
|
|
|
152
180
|
if (uglify) {
|
|
153
|
-
res =
|
|
181
|
+
res = await deserializeE2E(args, serverE2E_PublicKey, clientPrivateKey);
|
|
154
182
|
} else res = args;
|
|
183
|
+
const sortedArgs = discloseSocketArguments([res, not_encrypted]);
|
|
155
184
|
|
|
156
|
-
callback?.(...
|
|
157
|
-
const args = [...arguments];
|
|
185
|
+
callback?.(...sortedArgs, ...typeof emitable === 'function' ? [async function () {
|
|
186
|
+
const [args, not_encrypted] = encloseSocketArguments([...arguments]);
|
|
158
187
|
let res;
|
|
159
188
|
|
|
160
189
|
if (uglify) {
|
|
161
|
-
res = serializeE2E(
|
|
190
|
+
res = (await serializeE2E(args, undefined, serverE2E_PublicKey))[0];
|
|
162
191
|
} else res = args;
|
|
163
192
|
|
|
164
|
-
|
|
193
|
+
emitable([res, not_encrypted]);
|
|
165
194
|
}] : []);
|
|
166
|
-
}
|
|
195
|
+
};
|
|
167
196
|
|
|
168
197
|
const emit = ({ timeout, promise, emittion: emittionx }) => new Promise(async (resolve, reject) => {
|
|
169
198
|
const [route, ...emittion] = emittionx;
|
|
@@ -176,41 +205,43 @@ class RNMT {
|
|
|
176
205
|
|
|
177
206
|
let hasResolved, stime = Date.now();
|
|
178
207
|
|
|
179
|
-
const timer =
|
|
208
|
+
const timer = timeout ? setTimeout(() => {
|
|
180
209
|
hasResolved = true;
|
|
181
210
|
reject(new Error('emittion timeout'));
|
|
182
|
-
}, timeout);
|
|
211
|
+
}, timeout) : undefined;
|
|
183
212
|
|
|
184
213
|
await socketReadyPromise;
|
|
185
214
|
if (hasResolved) return;
|
|
186
215
|
clearTimeout(timer);
|
|
187
216
|
|
|
188
217
|
try {
|
|
189
|
-
const
|
|
218
|
+
const thisSocket = timeout ? socket.timeout(Math.max(timeout - (Date.now() - stime), 0)) : socket;
|
|
190
219
|
|
|
191
|
-
const lastEmit = emittion.slice(-1)[0]
|
|
192
|
-
|
|
220
|
+
const lastEmit = emittion.slice(-1)[0];
|
|
221
|
+
const hasEmitable = typeof lastEmit === 'function';
|
|
222
|
+
const [mit, not_encrypted] = encloseSocketArguments(hasEmitable ? emittion.slice(0, -1) : emittion);
|
|
193
223
|
|
|
194
|
-
const [reqBuilder, [privateKey]] = uglify ? serializeE2E(
|
|
224
|
+
const [reqBuilder, [privateKey]] = uglify ? await serializeE2E(mit, undefined, serverE2E_PublicKey) : [undefined, []];
|
|
195
225
|
|
|
196
|
-
if (
|
|
197
|
-
throw 'emitWithAck cannot have function in it
|
|
226
|
+
if (hasEmitable && promise)
|
|
227
|
+
throw 'emitWithAck cannot have function in it argument';
|
|
198
228
|
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
...
|
|
202
|
-
const args = [...arguments]
|
|
229
|
+
const result = await thisSocket[promise ? 'emitWithAck' : 'emit'](route,
|
|
230
|
+
[uglify ? reqBuilder : mit, not_encrypted],
|
|
231
|
+
...hasEmitable ? [async function () {
|
|
232
|
+
const [[args, not_encrypted]] = [...arguments];
|
|
203
233
|
let res;
|
|
204
234
|
|
|
205
235
|
if (uglify) {
|
|
206
|
-
res =
|
|
236
|
+
res = await deserializeE2E(args, serverE2E_PublicKey, privateKey);
|
|
207
237
|
} else res = args;
|
|
208
238
|
|
|
209
|
-
lastEmit(...res
|
|
239
|
+
lastEmit(...discloseSocketArguments([res, not_encrypted]));
|
|
210
240
|
}] : []
|
|
211
241
|
);
|
|
212
|
-
|
|
213
|
-
|
|
242
|
+
if (promise && result) {
|
|
243
|
+
resolve(discloseSocketArguments([uglify ? await deserializeE2E(result[0], serverE2E_PublicKey, privateKey) : result[0], result[1]])[0]);
|
|
244
|
+
} else resolve();
|
|
214
245
|
} catch (e) {
|
|
215
246
|
reject(e);
|
|
216
247
|
}
|
|
@@ -219,12 +250,14 @@ class RNMT {
|
|
|
219
250
|
const init = async () => {
|
|
220
251
|
if (hasCancelled) return;
|
|
221
252
|
const mtoken = disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl];
|
|
222
|
-
const [reqBuilder, [privateKey]] = uglify ? serializeE2E({ accessKey, a_extras: authHandshake }, mtoken, serverE2E_PublicKey) : [null, []];
|
|
253
|
+
const [reqBuilder, [privateKey]] = uglify ? await serializeE2E({ accessKey, a_extras: authHandshake }, mtoken, serverE2E_PublicKey) : [null, []];
|
|
223
254
|
|
|
224
255
|
socket = io(`${wsPrefix}://${projectUrl.split('://')[1]}`, {
|
|
256
|
+
transports: ['websocket', 'polling', 'flashsocket'],
|
|
257
|
+
extraHeaders,
|
|
225
258
|
auth: uglify ? {
|
|
226
259
|
ugly: true,
|
|
227
|
-
e2e: reqBuilder
|
|
260
|
+
e2e: reqBuilder.toString('base64')
|
|
228
261
|
} : {
|
|
229
262
|
...mtoken ? { mtoken } : {},
|
|
230
263
|
a_extras: authHandshake,
|
|
@@ -259,15 +292,20 @@ class RNMT {
|
|
|
259
292
|
}
|
|
260
293
|
|
|
261
294
|
return {
|
|
262
|
-
timeout: (timeout) =>
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
295
|
+
timeout: (timeout) => {
|
|
296
|
+
if (timeout !== undefined && !Validator.POSITIVE_INTEGER(timeout))
|
|
297
|
+
throw `expected a positive integer for timeout but got ${timeout}`;
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
emitWithAck: function () {
|
|
301
|
+
return emit({
|
|
302
|
+
timeout,
|
|
303
|
+
promise: true,
|
|
304
|
+
emittion: [...arguments]
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
},
|
|
271
309
|
emit: function () { emit({ emittion: [...arguments] }) },
|
|
272
310
|
emitWithAck: function () {
|
|
273
311
|
return emit({
|
|
@@ -279,7 +317,7 @@ class RNMT {
|
|
|
279
317
|
if (restrictedRoute.includes(route))
|
|
280
318
|
throw `${route} is a restricted socket path, avoid using any of ${restrictedRoute}`;
|
|
281
319
|
const ref = ++socketListenerIte,
|
|
282
|
-
listener = listenerCallback(callback);
|
|
320
|
+
listener = listenerCallback(route, callback);
|
|
283
321
|
|
|
284
322
|
socketListenerList.push([ref, 'on', route, listener]);
|
|
285
323
|
if (socket) socket.on(route, listener);
|
|
@@ -293,7 +331,7 @@ class RNMT {
|
|
|
293
331
|
if (restrictedRoute.includes(route))
|
|
294
332
|
throw `${route} is a restricted socket path, avoid using any of ${restrictedRoute}`;
|
|
295
333
|
const ref = ++socketListenerIte,
|
|
296
|
-
listener = listenerCallback(callback);
|
|
334
|
+
listener = listenerCallback(route, callback);
|
|
297
335
|
|
|
298
336
|
socketListenerList.push([ref, 'once', route, listener]);
|
|
299
337
|
if (socket) socket.once(route, listener);
|
|
@@ -311,10 +349,31 @@ class RNMT {
|
|
|
311
349
|
}
|
|
312
350
|
}
|
|
313
351
|
}
|
|
352
|
+
};
|
|
314
353
|
|
|
315
|
-
|
|
316
|
-
|
|
354
|
+
class DoNotEncrypt {
|
|
355
|
+
constructor(value) {
|
|
356
|
+
this.value = value;
|
|
317
357
|
}
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
const encloseSocketArguments = (args) => {
|
|
361
|
+
const [encrypted, unencrypted] = [{}, {}];
|
|
362
|
+
|
|
363
|
+
args.forEach((v, i) => {
|
|
364
|
+
if (v instanceof DoNotEncrypt) {
|
|
365
|
+
unencrypted[i] = v.value;
|
|
366
|
+
} else encrypted[i] = v;
|
|
367
|
+
});
|
|
368
|
+
return [encrypted, unencrypted];
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const discloseSocketArguments = (args = []) => {
|
|
372
|
+
return args.map((obj, i) => Object.entries(obj).map(v => i ? [v[0], new DoNotEncrypt(v[1])] : v)).flat()
|
|
373
|
+
.sort((a, b) => (a[0] * 1) - (b[0] * 1)).map((v, i) => {
|
|
374
|
+
if (v[0] * 1 !== i) throw 'corrupted socket arguments';
|
|
375
|
+
return v[1];
|
|
376
|
+
});
|
|
318
377
|
}
|
|
319
378
|
|
|
320
379
|
const validateReleaseCacheProp = (prop) => {
|
|
@@ -333,6 +392,11 @@ const validateReleaseCacheProp = (prop) => {
|
|
|
333
392
|
throw `Invalid value supplied to "io.${k}", expected a function but got "${v}"`;
|
|
334
393
|
} else throw `Unexpected property named "io.${k}"`;
|
|
335
394
|
});
|
|
395
|
+
} else if (k === 'promoteCache') {
|
|
396
|
+
if (typeof v !== 'boolean') throw 'promoteCache should be a boolean';
|
|
397
|
+
} else if (k === 'heapMemory') {
|
|
398
|
+
if (typeof v !== 'number' || v <= 0)
|
|
399
|
+
throw `Invalid value supplied to heapMemory, value must be an integer greater than zero`;
|
|
336
400
|
} else throw `Unexpected property named ${k}`;
|
|
337
401
|
});
|
|
338
402
|
|
|
@@ -342,19 +406,15 @@ const validateReleaseCacheProp = (prop) => {
|
|
|
342
406
|
const validator = {
|
|
343
407
|
dbName: (v) => {
|
|
344
408
|
if (typeof v !== 'string' || !v.trim())
|
|
345
|
-
throw `Invalid value supplied to dbName, value must be
|
|
409
|
+
throw `Invalid value supplied to dbName, value must be a non-empty string`;
|
|
346
410
|
},
|
|
347
411
|
dbUrl: (v) => {
|
|
348
412
|
if (typeof v !== 'string' || !v.trim())
|
|
349
|
-
throw `Invalid value supplied to dbUrl, value must be
|
|
350
|
-
},
|
|
351
|
-
heapMemory: (v) => {
|
|
352
|
-
if (typeof v !== 'number' || v <= 0)
|
|
353
|
-
throw `Invalid value supplied to heapMemory, value must be number and greater than zero`;
|
|
413
|
+
throw `Invalid value supplied to dbUrl, value must be a non-empty string`;
|
|
354
414
|
},
|
|
355
415
|
projectUrl: (v) => {
|
|
356
|
-
if (typeof v !== 'string' || !
|
|
357
|
-
throw `
|
|
416
|
+
if (typeof v !== 'string' || (!Validator.HTTPS(v) && !Validator.HTTP(v)))
|
|
417
|
+
throw `Expected "projectUrl" to be valid https or http link but got "${v}"`;
|
|
358
418
|
},
|
|
359
419
|
disableCache: (v) => {
|
|
360
420
|
if (typeof v !== 'boolean')
|
|
@@ -362,40 +422,57 @@ const validator = {
|
|
|
362
422
|
},
|
|
363
423
|
accessKey: (v) => {
|
|
364
424
|
if (typeof v !== 'string' || !v.trim())
|
|
365
|
-
throw `Invalid value supplied to accessKey, value must be a string
|
|
425
|
+
throw `Invalid value supplied to accessKey, value must be a non-empty string`;
|
|
366
426
|
},
|
|
367
427
|
maxRetries: (v) => {
|
|
368
|
-
if (
|
|
369
|
-
throw `Invalid value supplied to maxRetries, value must be
|
|
428
|
+
if (v <= 0 || !Validator.POSITIVE_INTEGER(v))
|
|
429
|
+
throw `Invalid value supplied to maxRetries, value must be positive integer greater than zero`;
|
|
370
430
|
},
|
|
371
431
|
enableE2E_Encryption: (v) => {
|
|
372
432
|
if (typeof v !== 'boolean')
|
|
373
433
|
throw `Invalid value supplied to enableE2E_Encryption, value must be a boolean`;
|
|
374
434
|
},
|
|
435
|
+
castBSON: v => {
|
|
436
|
+
if (typeof v !== 'boolean')
|
|
437
|
+
throw `Invalid value supplied to castBSON, value must be a boolean`;
|
|
438
|
+
},
|
|
439
|
+
borrowToken: v => {
|
|
440
|
+
if (typeof v !== 'string' || (!Validator.HTTPS(v) && !Validator.HTTP(v)))
|
|
441
|
+
throw `Expected "borrowToken" to be valid https or http link but got "${v}"`;
|
|
442
|
+
},
|
|
375
443
|
serverE2E_PublicKey: (v) => {
|
|
376
444
|
if (typeof v !== 'string' || !v.trim())
|
|
377
|
-
throw `Invalid value supplied to serverETE_PublicKey, value must be
|
|
445
|
+
throw `Invalid value supplied to serverETE_PublicKey, value must be a non-empty string`;
|
|
446
|
+
},
|
|
447
|
+
extraHeaders: v => {
|
|
448
|
+
if (!Validator.OBJECT(v)) throw '"extraHeaders" must be an object';
|
|
449
|
+
const reservedHeaders = ['mtoken', 'mosquito-token', 'init-content-type', 'content-type', 'authorization', 'uglified'];
|
|
450
|
+
|
|
451
|
+
Object.entries(v).forEach(([k, v]) => {
|
|
452
|
+
if (typeof v !== 'string') throw `expected a string at extraHeaders.${k} but got "${v}"`;
|
|
453
|
+
if (reservedHeaders.includes(v.toLowerCase()))
|
|
454
|
+
throw `extraHeaders must not include any reserved props which are: ${reservedHeaders}`;
|
|
455
|
+
});
|
|
378
456
|
}
|
|
379
457
|
};
|
|
380
458
|
|
|
381
459
|
const validateMTConfig = (config, that) => {
|
|
382
|
-
if (
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
for (let i = 0; i < h.length; i++) {
|
|
386
|
-
const k = h[i];
|
|
460
|
+
if (!Validator.OBJECT(config))
|
|
461
|
+
throw `${that.constructor.name} config is not an object`;
|
|
387
462
|
|
|
463
|
+
for (const [k, v] of Object.entries(config)) {
|
|
388
464
|
if (!validator[k]) throw `Unexpected property named ${k}`;
|
|
389
|
-
validator[k](
|
|
465
|
+
validator[k](v);
|
|
390
466
|
}
|
|
391
467
|
|
|
392
468
|
if (config.enableE2E_Encryption && !config.serverE2E_PublicKey)
|
|
393
469
|
throw '"serverE2E_PublicKey" is missing, enabling end-to-end encryption requires a public encryption key from the server';
|
|
394
|
-
if (!config
|
|
395
|
-
if (!config
|
|
470
|
+
if (!config.projectUrl) throw `projectUrl is a required property in ${that.constructor.name}() constructor`;
|
|
471
|
+
if (!config.accessKey) throw `accessKey is a required property in ${that.constructor.name}() constructor`;
|
|
396
472
|
}
|
|
397
473
|
|
|
398
474
|
export {
|
|
475
|
+
DoNotEncrypt,
|
|
399
476
|
TIMESTAMP,
|
|
400
477
|
DOCUMENT_EXTRACTION,
|
|
401
478
|
FIND_GEO_JSON,
|