@pi-r/mongodb 0.5.1 → 0.6.1

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/client/index.js CHANGED
@@ -9,14 +9,17 @@ const Db = require("@e-mc/db");
9
9
  const Request = require("@e-mc/request");
10
10
  const DbPool = require('@e-mc/db/pool');
11
11
  class MongoDBPool extends DbPool {
12
- getConnection() {
12
+ async getConnection() {
13
13
  return this.client.connect();
14
14
  }
15
- detach(force) {
15
+ async detach(force) {
16
16
  this.remove();
17
- return this.closed ? Promise.resolve() : this.close(force);
17
+ if (this.closed) {
18
+ return;
19
+ }
20
+ return this.close(force);
18
21
  }
19
- close(force = false) {
22
+ async close(force = false) {
20
23
  return this.client.close(force);
21
24
  }
22
25
  isEmpty() {
@@ -69,7 +72,7 @@ function getPoolKey(credential) {
69
72
  const options = credential.options;
70
73
  if (options && credential.uri) {
71
74
  const auth = options.auth;
72
- let result = credential.uri + (auth ? '_' + (auth.username || '') + '@' + (auth.password || '') : '') + '_' + (options.authMechanism || '') + Db.asString(options.authMechanismProperties);
75
+ let result = credential.uri + (auth ? '_' + (auth.username || '') + '@' + (auth.password || '') : '') + '_' + (options.authMechanism || '') + Db.asString(options.authMechanismProperties, true);
73
76
  if (options.tls || options.ssl) {
74
77
  const { tlsCertificateKeyFile = '', tlsCAFile = '', tlsCRLFile = '', tlsCertificateKeyFilePassword = '', tlsAllowInvalidHostnames, tlsAllowInvalidCertificates, tlsInsecure } = options;
75
78
  result += tlsCertificateKeyFile + tlsCAFile + tlsCRLFile + tlsCertificateKeyFilePassword + (tlsAllowInvalidHostnames ? '1' : '0') + (tlsAllowInvalidCertificates ? '1' : '0') + (tlsInsecure ? '1' : '0');
@@ -107,13 +110,10 @@ function setCredential(item) {
107
110
  else {
108
111
  options.auth || (options.auth = { username, password });
109
112
  }
110
- if (uri.indexOf('?') === -1) {
111
- if (uri[uri.length - 1] !== '/') {
112
- uri += '/';
113
- }
114
- uri += '?';
113
+ if (!uri.includes('?')) {
114
+ uri += (uri.endsWith('/') ? '' : '/') + '?';
115
115
  }
116
- uri += (uri[uri.length - 1] !== '?' ? '&' : '') + 'authMechanism=' + encodeURIComponent(authMechanism);
116
+ uri += (uri.endsWith('?') ? '' : '&') + 'authMechanism=' + encodeURIComponent(authMechanism);
117
117
  switch (authMechanism) {
118
118
  case 'MONGODB-X509': {
119
119
  const checkFile = (value) => {
@@ -175,53 +175,52 @@ function setCredential(item) {
175
175
  throw (0, types_1.errorMessage)("mongodb" /* STRINGS.MODULE_NAME */, 'Not defined - credentials');
176
176
  }
177
177
  const usePool = item.usePool;
178
- if (usePool) {
179
- let username, password, pool;
180
- if (typeof usePool === 'string' && (username = options.auth?.username || item.uri && (0, util_1.parseConnectionString)(item.uri)?.username)) {
181
- [password, pool] = DbPool.validateKey(POOL_STATE, username, usePool);
182
- if (pool) {
183
- pool.add(item, password);
184
- return;
185
- }
178
+ if (!usePool) {
179
+ return;
180
+ }
181
+ let username, password, pool;
182
+ if (typeof usePool === 'string' && (username = options.auth?.username || item.uri && (0, util_1.parseConnectionString)(item.uri)?.username)) {
183
+ [password, pool] = DbPool.validateKey(POOL_STATE, username, usePool);
184
+ if (pool) {
185
+ pool.add(item, password);
186
+ return;
186
187
  }
187
- const poolKey = getPoolKey(item);
188
- if (poolKey) {
189
- if (!(pool = POOL_STATE[poolKey]) || pool.closed) {
190
- const config = this.getPoolConfig("mongodb" /* STRINGS.MODULE_NAME */, password);
191
- if (config) {
192
- const { min, max, idle, queue_max, queue_idle, timeout, socket_timeout } = config;
193
- if (min >= 0) {
194
- options.minPoolSize ?? (options.minPoolSize = min);
195
- }
196
- if (max > 0) {
197
- options.maxPoolSize ?? (options.maxPoolSize = max);
198
- }
199
- if (idle >= 0) {
200
- options.maxIdleTimeMS ?? (options.maxIdleTimeMS = idle);
201
- }
202
- if (queue_max > 0) {
203
- options.maxConnecting ?? (options.maxConnecting = queue_max);
204
- }
205
- if (queue_idle >= 0) {
206
- options.waitQueueTimeoutMS ?? (options.waitQueueTimeoutMS = queue_idle);
207
- }
208
- if (timeout > 0) {
209
- options.connectTimeoutMS ?? (options.connectTimeoutMS = timeout);
210
- }
211
- if (socket_timeout > 0) {
212
- options.socketTimeoutMS ?? (options.socketTimeoutMS = socket_timeout);
213
- }
214
- }
215
- new MongoDBPool(new mongodb.MongoClient(item.uri, options), poolKey, username && password ? { username, password } : undefined).add(item).parent = POOL_STATE;
216
- }
217
- else {
218
- pool.add(item);
219
- }
188
+ }
189
+ const poolKey = getPoolKey(item);
190
+ if (!poolKey) {
191
+ item.usePool = false;
192
+ return;
193
+ }
194
+ if ((pool = POOL_STATE[poolKey]) && !pool.closed) {
195
+ pool.add(item);
196
+ return;
197
+ }
198
+ const config = this.getPoolConfig("mongodb" /* STRINGS.MODULE_NAME */, password);
199
+ if (config) {
200
+ const { min, max, idle, queue_max, queue_idle, timeout, socket_timeout } = config;
201
+ if (min >= 0) {
202
+ options.minPoolSize ?? (options.minPoolSize = min);
220
203
  }
221
- else {
222
- item.usePool = false;
204
+ if (max > 0) {
205
+ options.maxPoolSize ?? (options.maxPoolSize = max);
206
+ }
207
+ if (idle >= 0) {
208
+ options.maxIdleTimeMS ?? (options.maxIdleTimeMS = idle);
209
+ }
210
+ if (queue_max > 0) {
211
+ options.maxConnecting ?? (options.maxConnecting = queue_max);
212
+ }
213
+ if (queue_idle >= 0) {
214
+ options.waitQueueTimeoutMS ?? (options.waitQueueTimeoutMS = queue_idle);
215
+ }
216
+ if (timeout > 0) {
217
+ options.connectTimeoutMS ?? (options.connectTimeoutMS = timeout);
218
+ }
219
+ if (socket_timeout > 0) {
220
+ options.socketTimeoutMS ?? (options.socketTimeoutMS = socket_timeout);
223
221
  }
224
222
  }
223
+ new MongoDBPool(new mongodb.MongoClient(item.uri, options), poolKey, username && password ? { username, password } : undefined).add(item).parent = POOL_STATE;
225
224
  }
226
225
  exports.setCredential = setCredential;
227
226
  async function executeQuery(item, options) {
@@ -289,6 +288,9 @@ async function executeBatchQuery(batch, options = '', outResult) {
289
288
  item.transactionState &= ~64 /* DB_TRANSACTION.AUTH */;
290
289
  return client;
291
290
  };
291
+ if (this.host?.username) {
292
+ this.applyCommand(...batch);
293
+ }
292
294
  for (let i = 0; i < length; ++i) {
293
295
  const item = batch[i];
294
296
  const { source, name, table, id, aggregate, sort, client, cacheObjectKey, ignoreCache } = item;
@@ -312,17 +314,18 @@ async function executeBatchQuery(batch, options = '', outResult) {
312
314
  continue;
313
315
  }
314
316
  item.transactionState = 1 /* DB_TRANSACTION.ACTIVE */;
315
- const getCollection = (target) => target.db(name, client?.db).collection(table, client?.collection);
317
+ const getInstance = (target) => target.db(name, client?.db);
318
+ const getCollection = (target) => getInstance(target).collection(table, client?.collection);
319
+ const runCommand = async (target, document) => getInstance(target).command(document, client?.command);
316
320
  const credential = mongoCredential || onceCredential || getCacheObject(item);
317
- const renewCache = ignoreCache === 0;
318
- const cacheValue = renewCache ? { sessionKey, renewCache } : sessionKey;
321
+ const cacheValue = ignoreCache === undefined ? sessionKey : Array.isArray(ignoreCache) ? { sessionKey, exclusiveOf: ignoreCache } : { sessionKey, renewCache: ignoreCache === 0 };
319
322
  const coercing = this.hasCoerce("mongodb" /* STRINGS.MODULE_NAME */, 'options', credential.uuidKey);
320
323
  const targetObject = typeof checkObject === 'string' ? coercing && (0, types_1.asFunction)(checkObject) : checkObject;
321
324
  if (typeof streamRow === 'string') {
322
325
  streamRow = coercing && (0, types_1.asFunction)(streamRow);
323
326
  }
324
327
  let queryString = '', rows, pipeline;
325
- if ((caching && ignoreCache !== true || ignoreCache === false || ignoreCache === 1 || renewCache) && (!targetObject || typeof cacheObjectKey === 'string') && !streamRow) {
328
+ if (caching && ignoreCache !== true && (!targetObject || typeof cacheObjectKey === 'string') && !streamRow) {
326
329
  queryString = (name || '') + '_' + table + '_' + limit + Db.asString(sort, true) + Db.asString(client, true) + (targetObject ? targetObject.toString() + cacheObjectKey : '');
327
330
  }
328
331
  if (aggregate) {
@@ -373,11 +376,34 @@ async function executeBatchQuery(batch, options = '', outResult) {
373
376
  tasks[i] = new Promise(async (resolve, reject) => {
374
377
  let commandType;
375
378
  try {
379
+ const instance = mongoClient || await getConnection(item, credential);
380
+ const command = item.command;
381
+ if (command) {
382
+ await Promise.all((!Array.isArray(command) ? [command] : command).map(async (cmd) => runCommand(instance, cmd)))
383
+ .then(items => items.forEach(output => this.addLog(this.statusType.INFO, output, "mongodb" /* STRINGS.MODULE_NAME */, 'runCommand')));
384
+ }
385
+ const collection = getCollection(instance);
386
+ if (update && coercing) {
387
+ (0, types_1.coerceObject)(update);
388
+ }
389
+ if (Array.isArray(update)) {
390
+ commandType = this.commandType.INSERT;
391
+ const insertOptions = item.execute?.insert;
392
+ if (insertOptions && coercing) {
393
+ (0, types_1.coerceObject)(insertOptions);
394
+ }
395
+ if (update.length === 1) {
396
+ await collection.insertOne(update[0], insertOptions);
397
+ }
398
+ else if (update.length > 1) {
399
+ await collection.insertMany(update, insertOptions);
400
+ }
401
+ update = undefined;
402
+ }
376
403
  let cursor;
377
404
  if (pipeline || query) {
378
- const collection = getCollection(mongoClient || await getConnection(item, credential));
379
405
  if (pipeline) {
380
- const aggregateOptions = aggregate?.options;
406
+ const aggregateOptions = (0, types_1.isPlainObject)(aggregate) ? aggregate.options : undefined;
381
407
  if (coercing) {
382
408
  pipeline.forEach(doc => (0, types_1.coerceObject)(doc));
383
409
  if (aggregateOptions) {
@@ -393,41 +419,22 @@ async function executeBatchQuery(batch, options = '', outResult) {
393
419
  }
394
420
  }
395
421
  else {
396
- const [filter, command] = getFilterValue(query, coercing);
397
- if (update && coercing) {
398
- (0, types_1.coerceObject)(update);
399
- }
400
- if ((0, types_1.isArray)(update)) {
401
- commandType = this.commandType.INSERT;
402
- const insertOptions = item.execute?.insert;
403
- if (insertOptions && coercing) {
404
- (0, types_1.coerceObject)(insertOptions);
405
- }
406
- if (update.length === 1) {
407
- await collection.insertOne(update[0], insertOptions);
408
- }
409
- else {
410
- await collection.insertMany(update, insertOptions);
411
- }
412
- update = undefined;
413
- }
414
- else if (item.updateType === 1) {
415
- update = undefined;
416
- }
422
+ const [filter, operation] = getFilterValue(query, coercing);
423
+ const updateType = item.updateType;
417
424
  if (limit === 1) {
418
425
  let document;
419
426
  if (update) {
420
427
  commandType = this.commandType.UPDATE;
421
- document = await collection[item.updateType === 2 ? 'findOneAndReplace' : item.updateType === 3 ? 'findOneAndDelete' : 'findOneAndUpdate'](filter, update, command);
428
+ document = await collection[updateType === 2 ? 'findOneAndReplace' : updateType === 3 ? 'findOneAndDelete' : 'findOneAndUpdate'](filter, update, operation);
422
429
  }
423
430
  else {
424
431
  commandType = this.commandType.SELECT;
425
- document = await collection.findOne(filter, command);
432
+ document = await collection.findOne(filter, operation);
426
433
  }
427
434
  rows = document ? [document] : [];
428
435
  }
429
436
  else {
430
- if (update) {
437
+ if (update && updateType === 1) {
431
438
  commandType = this.commandType.UPDATE;
432
439
  const updateOptions = item.execute?.update;
433
440
  if (updateOptions && coercing) {
@@ -435,12 +442,12 @@ async function executeBatchQuery(batch, options = '', outResult) {
435
442
  }
436
443
  await collection.updateMany(filter, update, updateOptions);
437
444
  }
438
- cursor = collection.find(filter, command);
445
+ cursor = collection.find(filter, operation);
439
446
  }
440
447
  }
441
448
  }
442
449
  else if (!aggregate) {
443
- cursor = getCollection(mongoClient || await getConnection(item, credential)).find();
450
+ cursor = collection.find();
444
451
  }
445
452
  if (cursor) {
446
453
  commandType = this.commandType.SELECT;
@@ -518,12 +525,12 @@ async function executeBatchQuery(batch, options = '', outResult) {
518
525
  }
519
526
  }
520
527
  return this.processRows(batch, tasks, {
521
- disconnect: () => clients.forEach(item => item.close(true)),
528
+ disconnect: () => clients.forEach(async (item) => item.close(true)),
522
529
  parallel
523
530
  }, outResult);
524
531
  }
525
532
  exports.executeBatchQuery = executeBatchQuery;
526
- function checkTimeout(value, limit = 0) {
533
+ async function checkTimeout(value, limit = 0) {
527
534
  return DbPool.checkTimeout(POOL_STATE, value, limit);
528
535
  }
529
536
  exports.checkTimeout = checkTimeout;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-r/mongodb",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "MongoDB client driver for E-mc.",
5
5
  "main": "client/index.js",
6
6
  "types": "client/index.d.ts",
@@ -21,9 +21,9 @@
21
21
  "license": "MIT",
22
22
  "homepage": "https://github.com/anpham6/pi-r#readme",
23
23
  "dependencies": {
24
- "@e-mc/db": "^0.7.0",
25
- "@e-mc/request": "^0.7.0",
26
- "@e-mc/types": "^0.7.0",
24
+ "@e-mc/db": "^0.8.1",
25
+ "@e-mc/request": "^0.8.1",
26
+ "@e-mc/types": "^0.8.1",
27
27
  "mongodb": "^6.3.0"
28
28
  }
29
29
  }
package/types/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { DbDataSource } from '@e-mc/types/lib/squared';
2
2
 
3
3
  import type { CascadeAction, ServerAuth } from '@e-mc/types/lib/db';
4
4
 
5
- import type { AggregateOptions, CollectionOptions, CommandOperationOptions, DbOptions, Document, Filter, MongoClientOptions, OptionalUnlessRequiredId, Sort, SortDirection, UpdateFilter } from 'mongodb';
5
+ import type { AggregateOptions, CollectionOptions, CommandOperationOptions, DbOptions, Document, Filter, MongoClientOptions, OptionalUnlessRequiredId, RunCommandOptions, Sort, SortDirection, UpdateFilter } from 'mongodb';
6
6
 
7
7
  export interface MongoDBDataSource extends DbDataSource<Filter<Document> | MongoDBQueryWithOptions, MongoClientOptions, UpdateFilter<Document> | OptionalUnlessRequiredId<unknown>[], string | MongoDBCredential, string>, MongoDBClientDBOptions, CascadeAction {
8
8
  source: "mongodb";
@@ -26,12 +26,14 @@ export interface MongoDBClientDBOptions {
26
26
  client?: {
27
27
  db?: DbOptions;
28
28
  collection?: CollectionOptions;
29
+ command?: RunCommandOptions;
29
30
  };
30
31
  execute?: {
31
32
  insert?: CommandOperationOptions;
32
33
  update?: CommandOperationOptions;
33
34
  };
34
- aggregate?: MongoDBAggregate;
35
+ command?: ArrayOf<Document>;
36
+ aggregate?: MongoDBAggregate | Document[];
35
37
  sort?: Sort | string | MongoDBSortValue;
36
38
  }
37
39