mosquito-transport-js 0.3.3 → 0.3.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mosquito-transport-js",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Javascript web sdk for mosquito-transport (https://github.com/deflexable/mosquito-transport)",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -32,7 +32,7 @@
32
32
  "bson": "^6.8.0",
33
33
  "buffer": "^6.0.3",
34
34
  "crypto-js": "^4.2.0",
35
- "entity-serializer": "^1.0.0",
35
+ "entity-serializer": "^1.0.1",
36
36
  "guard-object": "^1.1.3",
37
37
  "limit-task": "1.0.0",
38
38
  "lodash.clonedeep": "^4.5.0",
@@ -117,7 +117,7 @@ export const getReachableServer = (projectUrl) => new Promise(resolve => {
117
117
  }, true);
118
118
  });
119
119
 
120
- export const buildFetchInterface = async ({ body, accessKey, authToken, method, uglify, serverE2E_PublicKey }) => {
120
+ export const buildFetchInterface = async ({ body, accessKey, authToken, method, uglify, serverE2E_PublicKey, extraHeaders }) => {
121
121
  if (!uglify) body = JSON.stringify({ ...body });
122
122
  const [plate, keyPair] = uglify ? await serializeE2E(body, authToken, serverE2E_PublicKey) : [undefined, []];
123
123
 
@@ -127,7 +127,8 @@ export const buildFetchInterface = async ({ body, accessKey, authToken, method,
127
127
  headers: {
128
128
  'Content-type': uglify ? 'request/buffer' : 'application/json',
129
129
  'Authorization': accessKey,
130
- ...((authToken && !uglify) ? { 'Mosquito-Token': authToken } : {})
130
+ ...(authToken && !uglify) ? { 'Mosquito-Token': authToken } : {},
131
+ ...extraHeaders
131
132
  },
132
133
  method: method || 'POST'
133
134
  }, keyPair];
package/src/index.d.ts CHANGED
@@ -16,6 +16,12 @@ interface MTConfig {
16
16
  * this is the base64 public key for end-to-end encryption on the server
17
17
  */
18
18
  serverE2E_PublicKey?: string;
19
+ /**
20
+ * extra headers that will be appended to all outgoing request in this instance
21
+ */
22
+ extraHeaders?: {
23
+ [key: string]: string
24
+ };
19
25
  /**
20
26
  * true to deserialize BSON values to their Node.js closest equivalent types
21
27
  *
@@ -54,6 +60,13 @@ export function FIND_GEO_JSON(coordinates: [latitude, longitude], offSetMeters:
54
60
 
55
61
  export const AUTH_PROVIDER_ID: auth_provider_id;
56
62
 
63
+ /**
64
+ * useful for avoiding encrypting data and extra overhead
65
+ */
66
+ export class DoNotEncrypt {
67
+ value: any;
68
+ }
69
+
57
70
  interface auth_provider_id {
58
71
  GOOGLE: 'google.com';
59
72
  FACEBOOK: 'facebook.com';
@@ -436,14 +449,27 @@ interface TokenManager {
436
449
 
437
450
  declare type Base64String = string;
438
451
 
439
- interface ReqOptions {
440
- awaitServer?: boolean;
452
+ interface UploadOptions {
453
+ /**
454
+ * optionally create hash for this upload to save disk space
455
+ */
441
456
  createHash?: boolean;
457
+ /**
458
+ * wait for a reachable server before initiating the upload task
459
+ */
460
+ awaitServer?: boolean;
461
+ }
462
+
463
+ interface DownloadOptions {
464
+ /**
465
+ * wait for a reachable server before initiating the download task
466
+ */
467
+ awaitServer?: boolean;
442
468
  }
443
469
 
444
470
  interface MTStorage {
445
- downloadFile: (link: string, onComplete?: (error?: ErrorResponse, filepath?: string) => void, destination?: string, onProgress?: (stats: DownloadProgressStats) => void) => () => void;
446
- uploadFile: (file: Base64String | Blob | Buffer | File, destination: string, onComplete?: (error?: ErrorResponse, downloadUrl?: string) => void, onProgress?: (stats: UploadProgressStats) => void, options?: ReqOptions) => () => void;
471
+ downloadFile: (link: string, onComplete?: (error?: ErrorResponse, filepath?: string) => void, destination?: string, onProgress?: (stats: DownloadProgressStats) => void, options?: DownloadOptions) => () => void;
472
+ uploadFile: (file: Base64String | Blob | File | Buffer, destination: string, onComplete?: (error?: ErrorResponse, downloadUrl?: string) => void, onProgress?: (stats: UploadProgressStats) => void, options?: UploadOptions) => () => void;
447
473
  deleteFile: (path: string) => Promise<void>;
448
474
  deleteFolder: (folder: string) => Promise<void>;
449
475
  }
@@ -467,13 +493,13 @@ interface ErrorResponse {
467
493
  }
468
494
 
469
495
  /** @public */
470
- export declare type Sort = string | Exclude<SortDirection, {
496
+ declare type Sort = string | Exclude<SortDirection, {
471
497
  $meta: string;
472
498
  }> | string[] | {
473
499
  [key: string]: SortDirection;
474
500
  } | Map<string, SortDirection> | [string, SortDirection][] | [string, SortDirection];
475
501
 
476
502
  /** @public */
477
- export declare type SortDirection = 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending' | {
503
+ declare type SortDirection = 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending' | {
478
504
  $meta: string;
479
505
  };
package/src/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import './polyfill';
2
1
  import { deserializeE2E, listenReachableServer, serializeE2E } from "./helpers/peripherals";
3
2
  import { releaseCacheStore, awaitStore } from "./helpers/utils";
4
3
  import { CacheStore, Scoped } from "./helpers/variables";
@@ -45,7 +44,7 @@ export class MosquitoTransport {
45
44
  maxRetries: config.maxRetries || 3,
46
45
  uglify: config.enableE2E_Encryption
47
46
  };
48
- const { projectUrl } = this.config;
47
+ const { projectUrl, extraHeaders } = this.config;
49
48
 
50
49
  this.config.secureUrl = projectUrl.startsWith('https');
51
50
  this.config.baseUrl = projectUrl.split('://')[1];
@@ -66,6 +65,7 @@ export class MosquitoTransport {
66
65
 
67
66
  const socket = io(`${this.config.wsPrefix}://${this.config.baseUrl}`, {
68
67
  transports: ['websocket', 'polling', 'flashsocket'],
68
+ extraHeaders,
69
69
  auth: {
70
70
  _m_internal: true,
71
71
  _from_base: true
@@ -153,7 +153,7 @@ export class MosquitoTransport {
153
153
 
154
154
  getSocket = (configOpts) => {
155
155
  const { disableAuth, authHandshake } = configOpts || {};
156
- const { projectUrl, uglify, accessKey, serverE2E_PublicKey, wsPrefix } = this.config;
156
+ const { projectUrl, uglify, accessKey, serverE2E_PublicKey, wsPrefix, extraHeaders } = this.config;
157
157
 
158
158
  const restrictedRoute = [
159
159
  _listenCollection,
@@ -184,22 +184,23 @@ export class MosquitoTransport {
184
184
  return;
185
185
  }
186
186
 
187
- const [args, emitable] = [...arguments];
187
+ const [[args, not_encrypted], emitable] = [...arguments];
188
188
  let res;
189
189
 
190
190
  if (uglify) {
191
191
  res = await deserializeE2E(args, serverE2E_PublicKey, clientPrivateKey);
192
192
  } else res = args;
193
+ const sortedArgs = discloseSocketArguments([res, not_encrypted]);
193
194
 
194
- callback?.(...res || [], ...typeof emitable === 'function' ? [async function () {
195
- const args = [...arguments];
195
+ callback?.(...sortedArgs, ...typeof emitable === 'function' ? [async function () {
196
+ const [args, not_encrypted] = encloseSocketArguments([...arguments]);
196
197
  let res;
197
198
 
198
199
  if (uglify) {
199
200
  res = (await serializeE2E(args, undefined, serverE2E_PublicKey))[0];
200
201
  } else res = args;
201
202
 
202
- emitable(res);
203
+ emitable([res, not_encrypted]);
203
204
  }] : []);
204
205
  };
205
206
 
@@ -228,7 +229,7 @@ export class MosquitoTransport {
228
229
 
229
230
  const lastEmit = emittion.slice(-1)[0];
230
231
  const hasEmitable = typeof lastEmit === 'function';
231
- const mit = hasEmitable ? emittion.slice(0, -1) : emittion;
232
+ const [mit, not_encrypted] = encloseSocketArguments(hasEmitable ? emittion.slice(0, -1) : emittion);
232
233
 
233
234
  const [reqBuilder, [privateKey]] = uglify ? await serializeE2E(mit, undefined, serverE2E_PublicKey) : [undefined, []];
234
235
 
@@ -236,20 +237,21 @@ export class MosquitoTransport {
236
237
  throw 'emitWithAck cannot have function in it argument';
237
238
 
238
239
  const result = await thisSocket[promise ? 'emitWithAck' : 'emit'](route,
239
- uglify ? reqBuilder : mit,
240
+ [uglify ? reqBuilder : mit, not_encrypted],
240
241
  ...hasEmitable ? [async function () {
241
- const [args] = [...arguments];
242
+ const [[args, not_encrypted]] = [...arguments];
242
243
  let res;
243
244
 
244
245
  if (uglify) {
245
246
  res = await deserializeE2E(args, serverE2E_PublicKey, privateKey);
246
247
  } else res = args;
247
248
 
248
- lastEmit(...res || []);
249
+ lastEmit(...discloseSocketArguments([res, not_encrypted]));
249
250
  }] : []
250
251
  );
251
-
252
- resolve((promise && result) ? uglify ? (await deserializeE2E(result, serverE2E_PublicKey, privateKey))[0] : result[0] : undefined);
252
+ if (promise && result) {
253
+ resolve(discloseSocketArguments([uglify ? await deserializeE2E(result[0], serverE2E_PublicKey, privateKey) : result[0], result[1]])[0]);
254
+ } else resolve();
253
255
  } catch (e) {
254
256
  reject(e);
255
257
  }
@@ -262,9 +264,10 @@ export class MosquitoTransport {
262
264
 
263
265
  socket = io(`${wsPrefix}://${projectUrl.split('://')[1]}`, {
264
266
  transports: ['websocket', 'polling', 'flashsocket'],
267
+ extraHeaders,
265
268
  auth: uglify ? {
266
269
  ugly: true,
267
- e2e: reqBuilder
270
+ e2e: reqBuilder.toString('base64')
268
271
  } : {
269
272
  ...mtoken ? { mtoken } : {},
270
273
  a_extras: authHandshake,
@@ -358,6 +361,31 @@ export class MosquitoTransport {
358
361
  }
359
362
  };
360
363
 
364
+ class DoNotEncrypt {
365
+ constructor(value) {
366
+ this.value = value;
367
+ }
368
+ };
369
+
370
+ const encloseSocketArguments = (args) => {
371
+ const [encrypted, unencrypted] = [{}, {}];
372
+
373
+ args.forEach((v, i) => {
374
+ if (v instanceof DoNotEncrypt) {
375
+ unencrypted[i] = v.value;
376
+ } else encrypted[i] = v;
377
+ });
378
+ return [encrypted, unencrypted];
379
+ }
380
+
381
+ const discloseSocketArguments = (args = []) => {
382
+ return args.map((obj, i) => Object.entries(obj).map(v => i ? [v[0], new DoNotEncrypt(v[1])] : v)).flat()
383
+ .sort((a, b) => (a[0] * 1) - (b[0] * 1)).map((v, i) => {
384
+ if (v[0] * 1 !== i) throw 'corrupted socket arguments';
385
+ return v[1];
386
+ });
387
+ }
388
+
361
389
  const validateReleaseCacheProp = (prop) => {
362
390
  const cacheList = [...Object.values(CACHE_PROTOCOL)];
363
391
 
@@ -425,6 +453,16 @@ const validator = {
425
453
  serverE2E_PublicKey: (v) => {
426
454
  if (typeof v !== 'string' || !v.trim())
427
455
  throw `Invalid value supplied to serverETE_PublicKey, value must be a non-empty string`;
456
+ },
457
+ extraHeaders: v => {
458
+ if (!Validator.OBJECT(v)) throw '"extraHeaders" must be an object';
459
+ const reservedHeaders = ['mtoken', 'mosquito-token', 'init-content-type', 'content-type', 'authorization', 'uglified'];
460
+
461
+ Object.entries(v).forEach(([k, v]) => {
462
+ if (typeof v !== 'string') throw `expected a string at extraHeaders.${k} but got "${v}"`;
463
+ if (reservedHeaders.includes(v.toLowerCase()))
464
+ throw `extraHeaders must not include any reserved props which are: ${reservedHeaders}`;
465
+ });
428
466
  }
429
467
  };
430
468
 
@@ -444,6 +482,7 @@ const validateMTConfig = (config, that) => {
444
482
  }
445
483
 
446
484
  export {
485
+ DoNotEncrypt,
447
486
  TIMESTAMP,
448
487
  DOCUMENT_EXTRACTION,
449
488
  FIND_GEO_JSON,
@@ -2,7 +2,7 @@ import { doSignOut } from ".";
2
2
  import EngineApi from "../../helpers/engine_api";
3
3
  import { AuthTokenListener, TokenRefreshListener } from "../../helpers/listeners";
4
4
  import { decodeBinary, deserializeE2E, listenReachableServer } from "../../helpers/peripherals";
5
- import { awaitStore, buildFetchInterface, getPrefferTime, updateCacheStore } from "../../helpers/utils";
5
+ import { awaitStore, buildFetchInterface, buildFetchResult, getPrefferTime, updateCacheStore } from "../../helpers/utils";
6
6
  import { CacheStore, Scoped } from "../../helpers/variables";
7
7
  import { simplifyError } from "simplify-error";
8
8
 
@@ -75,8 +75,8 @@ export const initTokenRefresher = async (config, forceRefresh) => {
75
75
  };
76
76
 
77
77
  const refreshToken = (builder, processRef, remainRetries = 7, initialRetries = 7, isForceRefresh) => new Promise(async (resolve, reject) => {
78
- const { projectUrl, serverE2E_PublicKey, accessKey, uglify } = builder;
79
- const lostProcess = simplifyError('process_lost', 'The token refresh process has been lost and replace with another one');
78
+ const { projectUrl, serverE2E_PublicKey, accessKey, uglify, extraHeaders } = builder;
79
+ const lostProcess = simplifyError('process_lost', 'The token refresh process has been lost and replaced with another one');
80
80
 
81
81
  try {
82
82
  const { token, refreshToken: r_token } = CacheStore.AuthStore[projectUrl];
@@ -85,18 +85,22 @@ const refreshToken = (builder, processRef, remainRetries = 7, initialRetries = 7
85
85
  body: { token, r_token },
86
86
  accessKey,
87
87
  uglify,
88
- serverE2E_PublicKey
88
+ serverE2E_PublicKey,
89
+ extraHeaders
89
90
  });
90
91
 
91
- const r = await (await fetch(EngineApi._refreshAuthToken(projectUrl, uglify), reqBuilder)).json();
92
+ let data;
92
93
 
93
- if (processRef !== Scoped.LastTokenRefreshRef[projectUrl]) {
94
- reject(lostProcess.simpleError);
95
- return;
94
+ try {
95
+ data = await buildFetchResult(await fetch(EngineApi._refreshAuthToken(projectUrl, uglify), reqBuilder), uglify);
96
+ } finally {
97
+ if (processRef !== Scoped.LastTokenRefreshRef[projectUrl]) {
98
+ reject(lostProcess.simpleError);
99
+ return;
100
+ }
96
101
  }
97
- if (r.simpleError) throw r;
98
102
 
99
- const f = uglify ? await deserializeE2E(r.e2e, serverE2E_PublicKey, privateKey) : r;
103
+ const f = uglify ? await deserializeE2E(data, serverE2E_PublicKey, privateKey) : data;
100
104
 
101
105
  if (CacheStore.AuthStore[projectUrl]) {
102
106
  CacheStore.AuthStore[projectUrl].token = f.result.token;
@@ -66,7 +66,7 @@ export class MTAuth {
66
66
  socket = io(`${wsPrefix}://${baseUrl}`, {
67
67
  transports: ['websocket', 'polling', 'flashsocket'],
68
68
  auth: uglify ? {
69
- e2e: reqBuilder,
69
+ e2e: reqBuilder.toString('base64'),
70
70
  _m_internal: true
71
71
  } : { mtoken, _m_internal: true },
72
72
  transports: ['websocket', 'polling', 'flashsocket']
@@ -167,7 +167,7 @@ export class MTAuth {
167
167
  };
168
168
 
169
169
  const doCustomSignin = (builder, email, password) => new Promise(async (resolve, reject) => {
170
- const { projectUrl, serverE2E_PublicKey, accessKey, uglify } = builder;
170
+ const { projectUrl, serverE2E_PublicKey, accessKey, uglify, extraHeaders } = builder;
171
171
 
172
172
  try {
173
173
  await awaitStore();
@@ -175,7 +175,8 @@ const doCustomSignin = (builder, email, password) => new Promise(async (resolve,
175
175
  body: { data: `${encodeBinary(email)}.${encodeBinary(password)}` },
176
176
  accessKey,
177
177
  serverE2E_PublicKey,
178
- uglify
178
+ uglify,
179
+ extraHeaders
179
180
  });
180
181
 
181
182
  const data = await buildFetchResult(await fetch(_customSignin(projectUrl, uglify), reqBuilder), uglify);
@@ -194,7 +195,7 @@ const doCustomSignin = (builder, email, password) => new Promise(async (resolve,
194
195
  });
195
196
 
196
197
  const doCustomSignup = (builder, email, password, name, metadata) => new Promise(async (resolve, reject) => {
197
- const { projectUrl, serverE2E_PublicKey, accessKey, uglify } = builder;
198
+ const { projectUrl, serverE2E_PublicKey, accessKey, uglify, extraHeaders } = builder;
198
199
 
199
200
  try {
200
201
  await awaitStore();
@@ -205,7 +206,8 @@ const doCustomSignup = (builder, email, password, name, metadata) => new Promise
205
206
  },
206
207
  accessKey,
207
208
  serverE2E_PublicKey,
208
- uglify
209
+ uglify,
210
+ extraHeaders
209
211
  });
210
212
 
211
213
  const data = await buildFetchResult(await fetch(_customSignup(projectUrl, uglify), reqBuilder), uglify);
@@ -237,7 +239,7 @@ export const clearCacheForSignout = (builder) => {
237
239
  export const doSignOut = async (builder) => {
238
240
  await awaitStore();
239
241
 
240
- const { projectUrl, serverE2E_PublicKey, accessKey, uglify } = builder,
242
+ const { projectUrl, serverE2E_PublicKey, accessKey, uglify, extraHeaders } = builder,
241
243
  { token, refreshToken: r_token } = CacheStore.AuthStore[projectUrl];
242
244
 
243
245
  clearCacheForSignout(builder);
@@ -251,11 +253,11 @@ export const doSignOut = async (builder) => {
251
253
  body: { token, r_token },
252
254
  accessKey,
253
255
  uglify,
254
- serverE2E_PublicKey
256
+ serverE2E_PublicKey,
257
+ extraHeaders
255
258
  });
256
259
 
257
- const r = await (await fetch(_signOut(projectUrl, uglify), reqBuilder)).json();
258
- if (r.simpleError) throw r;
260
+ await buildFetchResult(await fetch(_signOut(projectUrl, uglify), reqBuilder), uglify);
259
261
  } catch (e) {
260
262
  throw simplifyCaughtError(e).simpleError;
261
263
  }
@@ -263,7 +265,7 @@ export const doSignOut = async (builder) => {
263
265
  };
264
266
 
265
267
  const doGoogleSignin = (builder, token) => new Promise(async (resolve, reject) => {
266
- const { projectUrl, serverE2E_PublicKey, accessKey, uglify } = builder;
268
+ const { projectUrl, serverE2E_PublicKey, accessKey, uglify, extraHeaders } = builder;
267
269
 
268
270
  try {
269
271
  await awaitStore();
@@ -271,7 +273,8 @@ const doGoogleSignin = (builder, token) => new Promise(async (resolve, reject) =
271
273
  body: { token },
272
274
  accessKey,
273
275
  uglify,
274
- serverE2E_PublicKey
276
+ serverE2E_PublicKey,
277
+ extraHeaders
275
278
  });
276
279
 
277
280
  const data = await buildFetchResult(await fetch(_googleSignin(projectUrl, uglify), reqBuilder), uglify);
@@ -130,7 +130,7 @@ const {
130
130
  } = EngineApi;
131
131
 
132
132
  const listenDocument = (callback, onError, builder, config) => {
133
- const { projectUrl, wsPrefix, serverE2E_PublicKey, baseUrl, dbUrl, dbName, accessKey, path, disableCache, command, uglify, castBSON } = builder;
133
+ const { projectUrl, wsPrefix, serverE2E_PublicKey, baseUrl, dbUrl, dbName, accessKey, path, disableCache, command, uglify, extraHeaders, castBSON } = builder;
134
134
  const { find, findOne, sort, direction, limit } = command;
135
135
  const { disableAuth } = config || {};
136
136
  const shouldCache = !disableCache;
@@ -185,14 +185,14 @@ const listenDocument = (callback, onError, builder, config) => {
185
185
  const mtoken = disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl];
186
186
  const pureConfig = stripRequestConfig(config);
187
187
  const authObj = {
188
- commands: {
188
+ commands: stripUndefined({
189
189
  config: pureConfig && serializeToBase64(pureConfig),
190
190
  path,
191
191
  find: serializeToBase64(findOne || find),
192
192
  sort,
193
193
  direction,
194
194
  limit
195
- },
195
+ }),
196
196
  dbName,
197
197
  dbUrl
198
198
  };
@@ -201,7 +201,8 @@ const listenDocument = (callback, onError, builder, config) => {
201
201
 
202
202
  socket = io(`${wsPrefix}://${baseUrl}`, {
203
203
  transports: ['websocket', 'polling', 'flashsocket'],
204
- auth: uglify ? { e2e: encPlate, _m_internal: true } : {
204
+ extraHeaders,
205
+ auth: uglify ? { e2e: encPlate.toString('base64'), _m_internal: true } : {
205
206
  accessKey,
206
207
  _body: authObj,
207
208
  ...mtoken ? { mtoken } : {},
@@ -257,7 +258,7 @@ const listenDocument = (callback, onError, builder, config) => {
257
258
  };
258
259
 
259
260
  const initOnDisconnectionTask = (builder, value, type) => {
260
- const { projectUrl, wsPrefix, baseUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, path, command, uglify } = builder;
261
+ const { projectUrl, wsPrefix, baseUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, path, extraHeaders, command, uglify } = builder;
261
262
  const { find } = command || {};
262
263
  const disableAuth = false;
263
264
 
@@ -277,20 +278,21 @@ const initOnDisconnectionTask = (builder, value, type) => {
277
278
 
278
279
  const mtoken = disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl];
279
280
  const authObj = {
280
- commands: {
281
+ commands: stripUndefined({
281
282
  path,
282
283
  find: find && serializeToBase64(find),
283
284
  value: value && serializeToBase64({ _: value }),
284
285
  scope: type
285
- },
286
+ }),
286
287
  dbName,
287
288
  dbUrl
288
289
  };
289
290
 
290
291
  socket = io(`${wsPrefix}://${baseUrl}`, {
291
292
  transports: ['websocket', 'polling', 'flashsocket'],
293
+ extraHeaders,
292
294
  auth: uglify ? {
293
- e2e: (await serializeE2E({ accessKey, _body: authObj }, mtoken, serverE2E_PublicKey))[0],
295
+ e2e: (await serializeE2E({ accessKey, _body: authObj }, mtoken, serverE2E_PublicKey))[0].toString('base64'),
294
296
  _m_internal: true
295
297
  } : {
296
298
  ...mtoken ? { mtoken } : {},
@@ -337,7 +339,7 @@ const initOnDisconnectionTask = (builder, value, type) => {
337
339
  };
338
340
 
339
341
  const countCollection = async (builder, config) => {
340
- const { projectUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, maxRetries = 7, uglify, path, disableCache, command = {} } = builder;
342
+ const { projectUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, maxRetries = 7, uglify, extraHeaders, path, disableCache, command = {} } = builder;
341
343
  const { find } = command;
342
344
  const { disableAuth } = config || {};
343
345
  const accessId = await generateRecordID({ ...builder, countDoc: true }, config);
@@ -357,8 +359,8 @@ const countCollection = async (builder, config) => {
357
359
 
358
360
  const finalize = (a, b) => {
359
361
  if (Validator.NUMBER(a)) {
360
- reject(b);
361
- } else resolve(a);
362
+ resolve(a);
363
+ } else reject(b);
362
364
  };
363
365
 
364
366
  try {
@@ -374,7 +376,8 @@ const countCollection = async (builder, config) => {
374
376
  accessKey,
375
377
  ...disableAuth ? {} : { authToken: Scoped.AuthJWTToken[projectUrl] },
376
378
  serverE2E_PublicKey,
377
- uglify
379
+ uglify,
380
+ extraHeaders
378
381
  });
379
382
 
380
383
  const data = await buildFetchResult(await fetch(_documentCount(projectUrl, uglify), reqBuilder), uglify);
@@ -419,13 +422,17 @@ const stripRequestConfig = (config) => {
419
422
  return requestConfig.length ? Object.fromEntries(requestConfig) : undefined;
420
423
  };
421
424
 
425
+ const stripUndefined = o => Object.fromEntries(
426
+ Object.entries(o).filter(v => v[1] !== undefined)
427
+ );
428
+
422
429
  const transformBSON = (d, castBSON) => {
423
430
  if (castBSON) return d && deserializeBSON(serializeToBase64({ _: d }), true)._;
424
431
  return cloneDeep(d);
425
432
  };
426
433
 
427
434
  const findObject = async (builder, config) => {
428
- const { projectUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, maxRetries = 7, path, disableCache, uglify, command, castBSON } = builder;
435
+ const { projectUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, maxRetries = 7, path, disableCache, uglify, extraHeaders, command, castBSON } = builder;
429
436
  const { find, findOne, sort, direction, limit, random } = command;
430
437
  const { retrieval = RETRIEVAL.DEFAULT, episode = 0, disableAuth, disableMinimizer } = config || {};
431
438
  const enableMinimizer = !disableMinimizer;
@@ -498,7 +505,7 @@ const findObject = async (builder, config) => {
498
505
 
499
506
  const [reqBuilder, [privateKey]] = await buildFetchInterface({
500
507
  body: {
501
- commands: {
508
+ commands: stripUndefined({
502
509
  config: pureConfig && serializeToBase64(pureConfig),
503
510
  path,
504
511
  find: serializeToBase64(findOne || find),
@@ -506,14 +513,15 @@ const findObject = async (builder, config) => {
506
513
  direction,
507
514
  limit,
508
515
  random
509
- },
516
+ }),
510
517
  dbName,
511
518
  dbUrl
512
519
  },
513
520
  accessKey,
514
521
  authToken: disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl],
515
522
  serverE2E_PublicKey,
516
- uglify
523
+ uglify,
524
+ extraHeaders
517
525
  });
518
526
 
519
527
  const data = await buildFetchResult(await fetch((findOne ? _readDocument : _queryCollection)(projectUrl, uglify), reqBuilder), uglify);
@@ -587,7 +595,7 @@ const commitData = async (builder, value, type, config) => {
587
595
  )._;
588
596
  }
589
597
 
590
- const { projectUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, maxRetries = 7, path, find, disableCache, uglify } = builder;
598
+ const { projectUrl, serverE2E_PublicKey, dbUrl, dbName, accessKey, maxRetries = 7, path, find, disableCache, uglify, extraHeaders } = builder;
591
599
  const { disableAuth, delivery = DELIVERY.DEFAULT, stepping } = config || {};
592
600
  const writeId = `${Date.now() + ++Scoped.PendingIte}`;
593
601
  const isBatchWrite = type === 'batchWrite';
@@ -634,21 +642,22 @@ const commitData = async (builder, value, type, config) => {
634
642
 
635
643
  const [reqBuilder, [privateKey]] = await buildFetchInterface({
636
644
  body: {
637
- commands: {
645
+ commands: stripUndefined({
638
646
  value: value && serializeToBase64({ _: value }),
639
647
  ...isBatchWrite ? { stepping } : {
640
648
  path,
641
649
  scope: type,
642
650
  find: find && serializeToBase64(find)
643
651
  }
644
- },
652
+ }),
645
653
  dbName,
646
654
  dbUrl
647
655
  },
648
656
  accessKey,
649
657
  serverE2E_PublicKey,
650
658
  authToken: disableAuth ? undefined : Scoped.AuthJWTToken[projectUrl],
651
- uglify
659
+ uglify,
660
+ extraHeaders
652
661
  });
653
662
 
654
663
  const data = await buildFetchResult(await fetch((isBatchWrite ? _writeMapDocument : _writeDocument)(projectUrl, uglify), reqBuilder), uglify);
@@ -33,7 +33,7 @@ const buildFetchData = (data) => {
33
33
  }
34
34
 
35
35
  export const mfetch = async (input = '', init, config) => {
36
- const { projectUrl, serverE2E_PublicKey, method, maxRetries = 7, disableCache, accessKey, uglify } = config;
36
+ const { projectUrl, serverE2E_PublicKey, method, maxRetries = 7, disableCache, accessKey, uglify, extraHeaders } = config;
37
37
  const { headers, body } = init || {};
38
38
 
39
39
  if (method !== undefined)
@@ -153,6 +153,7 @@ export const mfetch = async (input = '', init, config) => {
153
153
  ...uglified ? { body: reqBuilder } : {},
154
154
  cache: 'no-cache',
155
155
  headers: {
156
+ ...extraHeaders,
156
157
  ...isBaseUrl ? {} : { 'content-type': 'application/json' },
157
158
  ...rawHeader,
158
159
  ...uglified ? {
@@ -12,6 +12,7 @@ export class MTStorage {
12
12
  }
13
13
 
14
14
  uploadFile = (file, destination, onComplete, onProgress, reqOptions) => {
15
+ const { awaitServer, createHash } = reqOptions || {};
15
16
  let hasCancelled = false,
16
17
  hasFinished = false,
17
18
  xhr;
@@ -44,7 +45,6 @@ export class MTStorage {
44
45
 
45
46
  const { projectUrl, accessKey, uglify } = this.builder;
46
47
  xhr = new XMLHttpRequest();
47
- const { awaitServer, createHash } = reqOptions || {};
48
48
 
49
49
  if (awaitServer) await awaitReachableServer(projectUrl);
50
50
  await awaitRefreshToken(projectUrl);
package/src/polyfill.js DELETED
@@ -1,3 +0,0 @@
1
- import { Buffer } from "buffer";
2
-
3
- if (!globalThis.Buffer) globalThis.Buffer = Buffer;