@abejarano/ts-mongodb-criteria 1.9.0 → 1.10.0

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/README.md CHANGED
@@ -214,6 +214,9 @@ await MongoTransaction.run(async (tx) => {
214
214
  await userRepository.upsert(user, tx)
215
215
  await auditRepository.upsert(auditEntry, tx)
216
216
  await sessionRepository.delete({ userId: user.getId() }, undefined, tx)
217
+
218
+ // Reads can observe writes made earlier in this transaction.
219
+ const persistedUser = await userRepository.one({ id: user.getId() }, tx)
217
220
  })
218
221
  ```
219
222
 
@@ -232,8 +235,8 @@ async deactivateUser(id: string, tx: MongoTransaction): Promise<void> {
232
235
 
233
236
  MongoDB transactions require a replica set or a sharded cluster; standalone
234
237
  MongoDB instances do not support them. This initial API applies the transaction
235
- context only to `upsert`, `delete`, and protected `updateOne`; `one` and `list`
236
- remain regular reads.
238
+ context to `upsert`, `delete`, protected `updateOne`, `one`, and `list`.
239
+ Pass `tx` as the third argument to `list` after `fieldsToExclude`.
237
240
 
238
241
  **Your First Query in 30 Seconds:**
239
242
 
@@ -11,9 +11,12 @@ class MongoRepository {
11
11
  this.criteriaConverter = new MongoCriteriaConverter_1.MongoCriteriaConverter();
12
12
  }
13
13
  /** Finds a single entity and hydrates it via the aggregate's fromPrimitives. */
14
- async one(filter) {
14
+ async one(filter, transaction) {
15
15
  const collection = await this.collection();
16
- const result = await collection.findOne(filter);
16
+ const session = MongoTransaction_1.MongoTransaction.sessionFor(transaction);
17
+ const result = session
18
+ ? await collection.findOne(filter, { session })
19
+ : await collection.findOne(filter);
17
20
  if (!result) {
18
21
  return null;
19
22
  }
@@ -27,9 +30,9 @@ class MongoRepository {
27
30
  await this.persist(entity.getId(), entity, transaction);
28
31
  }
29
32
  /** Lists entities by criteria and returns a paginated response. */
30
- async list(criteria, fieldsToExclude = []) {
31
- const documents = await this.searchByCriteria(criteria, fieldsToExclude);
32
- return this.paginate(documents);
33
+ async list(criteria, fieldsToExclude = [], transaction) {
34
+ const documents = await this.searchByCriteria(criteria, fieldsToExclude, transaction);
35
+ return this.paginate(documents, transaction);
33
36
  }
34
37
  /**
35
38
  * Deletes documents from the database based on a filter and optional options.
@@ -80,13 +83,14 @@ class MongoRepository {
80
83
  },
81
84
  }, transaction);
82
85
  }
83
- async searchByCriteria(criteria, fieldsToExclude = []) {
86
+ async searchByCriteria(criteria, fieldsToExclude = [], transaction) {
84
87
  this.criteria = criteria;
85
88
  this.query = this.criteriaConverter.convert(criteria);
86
89
  const collection = await this.collection();
90
+ const session = MongoTransaction_1.MongoTransaction.sessionFor(transaction);
87
91
  if (fieldsToExclude.length === 0) {
88
92
  const results = await collection
89
- .find(this.query.filter, {})
93
+ .find(this.query.filter, session ? { session } : {})
90
94
  .sort(this.query.sort)
91
95
  .skip(this.query.skip)
92
96
  .limit(this.query.limit)
@@ -98,16 +102,19 @@ class MongoRepository {
98
102
  projection[field] = 0;
99
103
  });
100
104
  const results = await collection
101
- .find(this.query.filter, { projection })
105
+ .find(this.query.filter, session ? { projection, session } : { projection })
102
106
  .sort(this.query.sort)
103
107
  .skip(this.query.skip)
104
108
  .limit(this.query.limit)
105
109
  .toArray();
106
110
  return results.map(({ _id, ...rest }) => rest);
107
111
  }
108
- async paginate(documents) {
112
+ async paginate(documents, transaction) {
109
113
  const collection = await this.collection();
110
- const count = await collection.countDocuments(this.query.filter);
114
+ const session = MongoTransaction_1.MongoTransaction.sessionFor(transaction);
115
+ const count = session
116
+ ? await collection.countDocuments(this.query.filter, { session })
117
+ : await collection.countDocuments(this.query.filter);
111
118
  const limit = this.criteria?.limit || 10;
112
119
  const currentPage = this.criteria?.currentPage || 1;
113
120
  const hasNextPage = currentPage * limit < count;
@@ -8,9 +8,12 @@ export class MongoRepository {
8
8
  this.criteriaConverter = new MongoCriteriaConverter();
9
9
  }
10
10
  /** Finds a single entity and hydrates it via the aggregate's fromPrimitives. */
11
- async one(filter) {
11
+ async one(filter, transaction) {
12
12
  const collection = await this.collection();
13
- const result = await collection.findOne(filter);
13
+ const session = MongoTransaction.sessionFor(transaction);
14
+ const result = session
15
+ ? await collection.findOne(filter, { session })
16
+ : await collection.findOne(filter);
14
17
  if (!result) {
15
18
  return null;
16
19
  }
@@ -24,9 +27,9 @@ export class MongoRepository {
24
27
  await this.persist(entity.getId(), entity, transaction);
25
28
  }
26
29
  /** Lists entities by criteria and returns a paginated response. */
27
- async list(criteria, fieldsToExclude = []) {
28
- const documents = await this.searchByCriteria(criteria, fieldsToExclude);
29
- return this.paginate(documents);
30
+ async list(criteria, fieldsToExclude = [], transaction) {
31
+ const documents = await this.searchByCriteria(criteria, fieldsToExclude, transaction);
32
+ return this.paginate(documents, transaction);
30
33
  }
31
34
  /**
32
35
  * Deletes documents from the database based on a filter and optional options.
@@ -77,13 +80,14 @@ export class MongoRepository {
77
80
  },
78
81
  }, transaction);
79
82
  }
80
- async searchByCriteria(criteria, fieldsToExclude = []) {
83
+ async searchByCriteria(criteria, fieldsToExclude = [], transaction) {
81
84
  this.criteria = criteria;
82
85
  this.query = this.criteriaConverter.convert(criteria);
83
86
  const collection = await this.collection();
87
+ const session = MongoTransaction.sessionFor(transaction);
84
88
  if (fieldsToExclude.length === 0) {
85
89
  const results = await collection
86
- .find(this.query.filter, {})
90
+ .find(this.query.filter, session ? { session } : {})
87
91
  .sort(this.query.sort)
88
92
  .skip(this.query.skip)
89
93
  .limit(this.query.limit)
@@ -95,16 +99,19 @@ export class MongoRepository {
95
99
  projection[field] = 0;
96
100
  });
97
101
  const results = await collection
98
- .find(this.query.filter, { projection })
102
+ .find(this.query.filter, session ? { projection, session } : { projection })
99
103
  .sort(this.query.sort)
100
104
  .skip(this.query.skip)
101
105
  .limit(this.query.limit)
102
106
  .toArray();
103
107
  return results.map(({ _id, ...rest }) => rest);
104
108
  }
105
- async paginate(documents) {
109
+ async paginate(documents, transaction) {
106
110
  const collection = await this.collection();
107
- const count = await collection.countDocuments(this.query.filter);
111
+ const session = MongoTransaction.sessionFor(transaction);
112
+ const count = session
113
+ ? await collection.countDocuments(this.query.filter, { session })
114
+ : await collection.countDocuments(this.query.filter);
108
115
  const limit = this.criteria?.limit || 10;
109
116
  const currentPage = this.criteria?.currentPage || 1;
110
117
  const hasNextPage = currentPage * limit < count;
@@ -3,8 +3,8 @@ import { AggregateRoot } from "../AggregateRoot";
3
3
  import { DeleteOptions } from "mongodb";
4
4
  import { MongoTransaction } from "./MongoTransaction";
5
5
  export interface IRepository<T extends AggregateRoot> {
6
- one(filter: object): Promise<T | null>;
7
- list<D>(criteria: Criteria, fieldsToExclude?: string[]): Promise<Paginate<D>>;
6
+ one(filter: object, transaction?: MongoTransaction): Promise<T | null>;
7
+ list<D>(criteria: Criteria, fieldsToExclude?: string[], transaction?: MongoTransaction): Promise<Paginate<D>>;
8
8
  upsert(entity: T, transaction?: MongoTransaction): Promise<void>;
9
9
  delete(filter: object, options?: DeleteOptions, transaction?: MongoTransaction): Promise<void>;
10
10
  }
@@ -11,11 +11,11 @@ export declare abstract class MongoRepository<T extends AggregateRoot> {
11
11
  protected constructor(aggregateRootClass: AggregateRootClass<T>);
12
12
  abstract collectionName(): string;
13
13
  /** Finds a single entity and hydrates it via the aggregate's fromPrimitives. */
14
- one(filter: object): Promise<T | null>;
14
+ one(filter: object, transaction?: MongoTransaction): Promise<T | null>;
15
15
  /** Upserts an aggregate by delegating to persist with its id. */
16
16
  upsert(entity: T, transaction?: MongoTransaction): Promise<void>;
17
17
  /** Lists entities by criteria and returns a paginated response. */
18
- list<D>(criteria: Criteria, fieldsToExclude?: string[]): Promise<Paginate<D>>;
18
+ list<D>(criteria: Criteria, fieldsToExclude?: string[], transaction?: MongoTransaction): Promise<Paginate<D>>;
19
19
  /**
20
20
  * Deletes documents from the database based on a filter and optional options.
21
21
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@abejarano/ts-mongodb-criteria",
3
3
  "author": "angel bejarano / angel.bejarano@jaspesoft.com",
4
- "version": "1.9.0",
4
+ "version": "1.10.0",
5
5
  "description": "Patrón Criteria para consultas MongoDB en TypeScript",
6
6
  "main": "dist/cjs/index.js",
7
7
  "module": "dist/esm/index.js",