@tmlmobilidade/databases 20260324.1432.27 → 20260324.1728.13

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.
@@ -42,7 +42,14 @@ export class GOMongoClient {
42
42
  async connect() {
43
43
  Logger.info('[GOMongoClient] Connecting to database...');
44
44
  const connectionString = await this.getConnectionString();
45
- this.client = new MongoClient(connectionString);
45
+ this.client = new MongoClient(connectionString, {
46
+ connectTimeoutMS: 10_000,
47
+ directConnection: process.env.GO_MONGO_TUNNEL_ENABLED === 'true',
48
+ maxPoolSize: 20,
49
+ minPoolSize: 2,
50
+ readPreference: 'secondaryPreferred',
51
+ serverSelectionTimeoutMS: 10_000,
52
+ });
46
53
  this.client.on('close', () => {
47
54
  console.warn('[GOMongoClient] Database connection closed unexpectedly.');
48
55
  });
@@ -42,7 +42,14 @@ export class PCGIFileManagerClient {
42
42
  async connect() {
43
43
  Logger.info('[PCGIFileManagerClient] Connecting to database...');
44
44
  const connectionString = await this.getConnectionString();
45
- this.client = new MongoClient(connectionString);
45
+ this.client = new MongoClient(connectionString, {
46
+ connectTimeoutMS: 10_000,
47
+ directConnection: process.env.PCGI_FILE_MANAGER_TUNNEL_ENABLED === 'true',
48
+ maxPoolSize: 20,
49
+ minPoolSize: 2,
50
+ readPreference: 'secondaryPreferred',
51
+ serverSelectionTimeoutMS: 10_000,
52
+ });
46
53
  this.client.on('close', () => {
47
54
  console.warn('[PCGIFileManagerClient] Database connection closed unexpectedly.');
48
55
  });
@@ -42,7 +42,14 @@ export class PCGIRawClient {
42
42
  async connect() {
43
43
  Logger.info('[PCGIRawClient] Connecting to database...');
44
44
  const connectionString = await this.getConnectionString();
45
- this.client = new MongoClient(connectionString);
45
+ this.client = new MongoClient(connectionString, {
46
+ connectTimeoutMS: 10_000,
47
+ directConnection: process.env.PCGI_RAW_TUNNEL_ENABLED === 'true',
48
+ maxPoolSize: 20,
49
+ minPoolSize: 2,
50
+ readPreference: 'secondaryPreferred',
51
+ serverSelectionTimeoutMS: 10_000,
52
+ });
46
53
  this.client.on('close', () => {
47
54
  console.warn('[PCGIRawClient] Database connection closed unexpectedly.');
48
55
  });
@@ -42,7 +42,14 @@ export class PCGITicketingClient {
42
42
  async connect() {
43
43
  Logger.info('[PCGITicketingClient] Connecting to database...');
44
44
  const connectionString = await this.getConnectionString();
45
- this.client = new MongoClient(connectionString);
45
+ this.client = new MongoClient(connectionString, {
46
+ connectTimeoutMS: 10_000,
47
+ directConnection: process.env.PCGI_TICKETING_TUNNEL_ENABLED === 'true',
48
+ maxPoolSize: 20,
49
+ minPoolSize: 2,
50
+ readPreference: 'secondaryPreferred',
51
+ serverSelectionTimeoutMS: 10_000,
52
+ });
46
53
  this.client.on('close', () => {
47
54
  console.warn('[PCGITicketingClient] Database connection closed unexpectedly.');
48
55
  });
@@ -42,7 +42,14 @@ export class PCGIValidationsClient {
42
42
  async connect() {
43
43
  Logger.info('[PCGIValidationsClient] Connecting to database...');
44
44
  const connectionString = await this.getConnectionString();
45
- this.client = new MongoClient(connectionString);
45
+ this.client = new MongoClient(connectionString, {
46
+ connectTimeoutMS: 10_000,
47
+ directConnection: process.env.PCGI_VALIDATIONS_TUNNEL_ENABLED === 'true',
48
+ maxPoolSize: 20,
49
+ minPoolSize: 2,
50
+ readPreference: 'secondaryPreferred',
51
+ serverSelectionTimeoutMS: 10_000,
52
+ });
46
53
  this.client.on('close', () => {
47
54
  console.warn('[PCGIValidationsClient] Database connection closed unexpectedly.');
48
55
  });
@@ -1,5 +1,5 @@
1
1
  /* * */
2
- import { isSameIndex, normalizeMongoIndex } from '../utils/mongo/index.js';
2
+ import { isSameIndex, prepareMongoIndexOptions } from '../utils/mongo/index.js';
3
3
  import { Logger } from '@tmlmobilidade/logger';
4
4
  /* * */
5
5
  export class MongoInterfaceTemplate {
@@ -212,12 +212,11 @@ export class MongoInterfaceTemplate {
212
212
  */
213
213
  async syncIndexes() {
214
214
  try {
215
+ Logger.info(`MONGODB [${this.collectionName}]: Synchronizing indexes...`);
215
216
  // Normalize already applied and new indexes
216
217
  // and filter the default _id index.
217
218
  const existingIndexes = await this.collection.indexes();
218
- const normalizedExisting = existingIndexes.map((normalizeMongoIndex));
219
- const filteredExisting = normalizedExisting.filter(idx => JSON.stringify(idx.key) !== JSON.stringify({ _id: 1 }));
220
- const normalizedDesired = this.indexDescription.map(idx => normalizeMongoIndex(idx));
219
+ const filteredExisting = existingIndexes.filter(idx => JSON.stringify(idx.key) !== JSON.stringify({ _id: 1 }));
221
220
  // Setup desired indexes based on indexDescription
222
221
  const indexesToDrop = [];
223
222
  const indexesToCreate = [];
@@ -225,13 +224,13 @@ export class MongoInterfaceTemplate {
225
224
  for (const existingIdx of filteredExisting) {
226
225
  // For the list of existing indexes,
227
226
  // check if they are present in the desired index description.
228
- const found = normalizedDesired.some(desiredIdx => isSameIndex(existingIdx, desiredIdx));
227
+ const found = this.indexDescription.some(desiredIdx => isSameIndex(existingIdx, desiredIdx));
229
228
  // If not, mark them for dropping.
230
229
  if (!found)
231
- indexesToDrop.push(existingIdx);
230
+ indexesToDrop.push(existingIdx.name);
232
231
  }
233
232
  // Find indexes to create
234
- for (const desiredIdx of normalizedDesired) {
233
+ for (const desiredIdx of this.indexDescription) {
235
234
  // For the list of desired indexes,
236
235
  // check if they are present in the existing indexes.
237
236
  const found = filteredExisting.some(existingIdx => isSameIndex(existingIdx, desiredIdx));
@@ -240,20 +239,20 @@ export class MongoInterfaceTemplate {
240
239
  indexesToCreate.push(desiredIdx);
241
240
  }
242
241
  // Drop indexes
243
- for (const idx of indexesToDrop) {
244
- if (!idx.name)
242
+ for (const idxName of indexesToDrop) {
243
+ if (!idxName)
245
244
  continue;
246
- await this.collection.dropIndex(idx.name);
245
+ Logger.info(`MONGODB [${this.collectionName}]: Dropping index ${idxName}.`);
246
+ await this.collection.dropIndex(idxName);
247
+ Logger.success(`MONGODB [${this.collectionName}]: Dropped index ${idxName}.`);
247
248
  }
248
249
  // Create indexes
249
250
  for (const idx of indexesToCreate) {
250
- await this.collection.createIndex(idx.key, {
251
- expireAfterSeconds: idx.expireAfterSeconds ?? undefined,
252
- sparse: idx.sparse,
253
- unique: idx.unique,
254
- });
251
+ Logger.info(`MONGODB [${this.collectionName}]: Creating index on keys ${JSON.stringify(idx.key)} with options ${JSON.stringify(prepareMongoIndexOptions(idx))}.`);
252
+ await this.collection.createIndex(idx.key, prepareMongoIndexOptions(idx));
253
+ Logger.success(`MONGODB [${this.collectionName}]: Created index on keys ${JSON.stringify(idx.key)}.`);
255
254
  }
256
- Logger.info(`MONGODB [${this.collectionName}]: Indexes synchronized.`);
255
+ Logger.success(`MONGODB [${this.collectionName}]: Indexes synchronized.`);
257
256
  }
258
257
  catch (error) {
259
258
  Logger.error(`MONGODB [${this.collectionName}]: Error @ syncIndexes(): ${error.message}`);
@@ -9,10 +9,3 @@ export interface SimplifiedMongoIndex<T> {
9
9
  sparse?: boolean;
10
10
  unique?: boolean;
11
11
  }
12
- /**
13
- * A MongoDB index description type that is normalized
14
- * to ensure all expected properties are present and have consistent types.
15
- */
16
- export type ComparableMongoIndex<T> = Required<SimplifiedMongoIndex<T>> & {
17
- name?: string;
18
- };
@@ -1,12 +1,13 @@
1
- import { type ComparableMongoIndex, type SimplifiedMongoIndex } from '../../types/mongo/index-description.js';
2
- import { type IndexDescriptionInfo } from 'mongodb';
1
+ import { type SimplifiedMongoIndex } from '../../types/mongo/index-description.js';
2
+ import { type CreateIndexesOptions, type IndexDescriptionInfo } from 'mongodb';
3
3
  /**
4
- * Normalizes a MongoDB index description by ensuring that
5
- * all expected properties are present and have consistent types.
6
- * @param indexDescription The original index description from MongoDB.
7
- * @returns A normalized index description with default values for missing properties.
4
+ * Prepares MongoDB index options by extracting relevant properties
5
+ * from a simplified index description. This function ensures that
6
+ * only valid options are included when creating indexes in MongoDB.
7
+ * @param idx A simplified index description defined by the user.
8
+ * @returns An object containing valid MongoDB index options based on the provided description.
8
9
  */
9
- export declare function normalizeMongoIndex<T>(indexDescription: IndexDescriptionInfo | SimplifiedMongoIndex<T>): ComparableMongoIndex<T>;
10
+ export declare function prepareMongoIndexOptions<T>(idx: SimplifiedMongoIndex<T>): CreateIndexesOptions;
10
11
  /**
11
12
  * Compares two normalized MongoDB index descriptions for equivalence.
12
13
  * Two indexes are considered the same if they have identical key definitions
@@ -15,4 +16,4 @@ export declare function normalizeMongoIndex<T>(indexDescription: IndexDescriptio
15
16
  * @param b The second normalized index description to compare.
16
17
  * @returns True if the indexes are considered the same, false otherwise.
17
18
  */
18
- export declare function isSameIndex<T>(a: ComparableMongoIndex<T>, b: ComparableMongoIndex<T>): boolean;
19
+ export declare function isSameIndex<T>(a: IndexDescriptionInfo | SimplifiedMongoIndex<T>, b: IndexDescriptionInfo | SimplifiedMongoIndex<T>): boolean;
@@ -1,13 +1,30 @@
1
1
  /* * */
2
+ /**
3
+ * Prepares MongoDB index options by extracting relevant properties
4
+ * from a simplified index description. This function ensures that
5
+ * only valid options are included when creating indexes in MongoDB.
6
+ * @param idx A simplified index description defined by the user.
7
+ * @returns An object containing valid MongoDB index options based on the provided description.
8
+ */
9
+ export function prepareMongoIndexOptions(idx) {
10
+ const result = {};
11
+ if (idx.expireAfterSeconds !== undefined)
12
+ result.expireAfterSeconds = idx.expireAfterSeconds;
13
+ if (idx.sparse !== undefined)
14
+ result.sparse = idx.sparse;
15
+ if (idx.unique !== undefined)
16
+ result.unique = idx.unique;
17
+ return result;
18
+ }
2
19
  /**
3
20
  * Normalizes a MongoDB index description by ensuring that
4
21
  * all expected properties are present and have consistent types.
5
- * @param indexDescription The original index description from MongoDB.
22
+ * @param indexDescription The existing indexes from MongoDB or a simplified structure defined by the user.
6
23
  * @returns A normalized index description with default values for missing properties.
7
24
  */
8
- export function normalizeMongoIndex(indexDescription) {
25
+ function normalizeMongoIndex(indexDescription) {
9
26
  return {
10
- expireAfterSeconds: indexDescription.expireAfterSeconds ?? null,
27
+ expireAfterSeconds: indexDescription.expireAfterSeconds ?? undefined,
11
28
  key: indexDescription.key,
12
29
  sparse: !!indexDescription.sparse,
13
30
  unique: !!indexDescription.unique,
@@ -22,14 +39,18 @@ export function normalizeMongoIndex(indexDescription) {
22
39
  * @returns True if the indexes are considered the same, false otherwise.
23
40
  */
24
41
  export function isSameIndex(a, b) {
42
+ // Normalize both index descriptions
43
+ // to ensure consistent comparison.
44
+ const normalizedA = normalizeMongoIndex(a);
45
+ const normalizedB = normalizeMongoIndex(b);
25
46
  // Sort keys to ensure consistent comparison regardless of order.
26
- const aKeySorted = Object.fromEntries(Object.entries(a.key).sort());
27
- const bKeySorted = Object.fromEntries(Object.entries(b.key).sort());
47
+ const aKeySorted = Object.fromEntries(Object.entries(normalizedA.key).sort());
48
+ const bKeySorted = Object.fromEntries(Object.entries(normalizedB.key).sort());
28
49
  // Check if keys are the same and if unique/sparse settings match.
29
50
  const matchingKeys = JSON.stringify(aKeySorted) === JSON.stringify(bKeySorted);
30
- const matchingUnique = !!a.unique === !!b.unique;
31
- const matchingSparse = !!a.sparse === !!b.sparse;
32
- const matchingExpire = a.expireAfterSeconds === b.expireAfterSeconds;
51
+ const matchingUnique = !!normalizedA.unique === !!normalizedB.unique;
52
+ const matchingSparse = !!normalizedA.sparse === !!normalizedB.sparse;
53
+ const matchingExpire = normalizedA.expireAfterSeconds === normalizedB.expireAfterSeconds;
33
54
  // Consider indexes the same if all properties match.
34
55
  return matchingKeys && matchingUnique && matchingSparse && matchingExpire;
35
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmlmobilidade/databases",
3
- "version": "20260324.1432.27",
3
+ "version": "20260324.1728.13",
4
4
  "author": {
5
5
  "email": "iso@tmlmobilidade.pt",
6
6
  "name": "TML-ISO"