@orion-js/mongodb 4.2.3 → 4.2.5

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/dist/index.d.cts CHANGED
@@ -335,6 +335,14 @@ declare function registerCollection(connectionName: string, collection: Collecti
335
335
  * @returns Array of registered collections for the connection
336
336
  */
337
337
  declare function getRegisteredCollections(connectionName?: string): Array<Collection<ModelClassBase>>;
338
+ /**
339
+ * Gets the merged indexes for a specific collection from the registry.
340
+ * This includes all indexes from all createCollection() calls for the same collection name.
341
+ * @param connectionName - The name of the MongoDB connection
342
+ * @param collectionName - The name of the collection
343
+ * @returns Array of merged index definitions, or empty array if collection not registered
344
+ */
345
+ declare function getMergedIndexes(connectionName: string, collectionName: string): CollectionIndex[];
338
346
  /**
339
347
  * Deletes unused indexes from all registered collections for a connection.
340
348
  * Iterates over all collections registered via createCollection() and
@@ -380,4 +388,4 @@ declare const ENCRYPTION_ALGORITHMS: {
380
388
  RANDOM: string;
381
389
  };
382
390
 
383
- export { BaseCollection, Collection, type CollectionIndex, type CountDocuments, type CreateCollectionOptions, type CreateCollectionOptionsWithSchemaType, type CreateCollectionOptionsWithTypedSchema, DataLoader, type DeleteMany, type DeleteOne, type DistinctDocumentId, type DocumentWithId, ENCRYPTION_ALGORITHMS, type EstimatedDocumentCount, type Find, type FindCursor, type FindOne, type FindOneAndUpdate, type FindOneAndUpdateUpdateOptions, type InferIdType, type InferSchemaTypeWithId, type InitItem, type InsertAndFind, type InsertMany, type InsertManyOptions, type InsertOne, type InsertOptions, type ModelClassBase, type ModelToMongoSelector, MongoCollection, type MongoFilter, type MongoSelector, type OptionalId, Repository, type SchemaWithRequiredId, type TypedId, type UpdateAndFind, type UpdateItem, type UpdateMany, type UpdateOne, type UpdateOptions, type Upsert, allConnectionPromises, collectionsRegistry, configureConnection, connections, createCollection, createIndexesPromises, deleteAllUnusedIndexes, getDBName, getMongoConnection, getOrCreateEncryptionKey, getRegisteredCollections, registerCollection, typedId };
391
+ export { BaseCollection, Collection, type CollectionIndex, type CountDocuments, type CreateCollectionOptions, type CreateCollectionOptionsWithSchemaType, type CreateCollectionOptionsWithTypedSchema, DataLoader, type DeleteMany, type DeleteOne, type DistinctDocumentId, type DocumentWithId, ENCRYPTION_ALGORITHMS, type EstimatedDocumentCount, type Find, type FindCursor, type FindOne, type FindOneAndUpdate, type FindOneAndUpdateUpdateOptions, type InferIdType, type InferSchemaTypeWithId, type InitItem, type InsertAndFind, type InsertMany, type InsertManyOptions, type InsertOne, type InsertOptions, type ModelClassBase, type ModelToMongoSelector, MongoCollection, type MongoFilter, type MongoSelector, type OptionalId, Repository, type SchemaWithRequiredId, type TypedId, type UpdateAndFind, type UpdateItem, type UpdateMany, type UpdateOne, type UpdateOptions, type Upsert, allConnectionPromises, collectionsRegistry, configureConnection, connections, createCollection, createIndexesPromises, deleteAllUnusedIndexes, getDBName, getMergedIndexes, getMongoConnection, getOrCreateEncryptionKey, getRegisteredCollections, registerCollection, typedId };
package/dist/index.d.ts CHANGED
@@ -335,6 +335,14 @@ declare function registerCollection(connectionName: string, collection: Collecti
335
335
  * @returns Array of registered collections for the connection
336
336
  */
337
337
  declare function getRegisteredCollections(connectionName?: string): Array<Collection<ModelClassBase>>;
338
+ /**
339
+ * Gets the merged indexes for a specific collection from the registry.
340
+ * This includes all indexes from all createCollection() calls for the same collection name.
341
+ * @param connectionName - The name of the MongoDB connection
342
+ * @param collectionName - The name of the collection
343
+ * @returns Array of merged index definitions, or empty array if collection not registered
344
+ */
345
+ declare function getMergedIndexes(connectionName: string, collectionName: string): CollectionIndex[];
338
346
  /**
339
347
  * Deletes unused indexes from all registered collections for a connection.
340
348
  * Iterates over all collections registered via createCollection() and
@@ -380,4 +388,4 @@ declare const ENCRYPTION_ALGORITHMS: {
380
388
  RANDOM: string;
381
389
  };
382
390
 
383
- export { BaseCollection, Collection, type CollectionIndex, type CountDocuments, type CreateCollectionOptions, type CreateCollectionOptionsWithSchemaType, type CreateCollectionOptionsWithTypedSchema, DataLoader, type DeleteMany, type DeleteOne, type DistinctDocumentId, type DocumentWithId, ENCRYPTION_ALGORITHMS, type EstimatedDocumentCount, type Find, type FindCursor, type FindOne, type FindOneAndUpdate, type FindOneAndUpdateUpdateOptions, type InferIdType, type InferSchemaTypeWithId, type InitItem, type InsertAndFind, type InsertMany, type InsertManyOptions, type InsertOne, type InsertOptions, type ModelClassBase, type ModelToMongoSelector, MongoCollection, type MongoFilter, type MongoSelector, type OptionalId, Repository, type SchemaWithRequiredId, type TypedId, type UpdateAndFind, type UpdateItem, type UpdateMany, type UpdateOne, type UpdateOptions, type Upsert, allConnectionPromises, collectionsRegistry, configureConnection, connections, createCollection, createIndexesPromises, deleteAllUnusedIndexes, getDBName, getMongoConnection, getOrCreateEncryptionKey, getRegisteredCollections, registerCollection, typedId };
391
+ export { BaseCollection, Collection, type CollectionIndex, type CountDocuments, type CreateCollectionOptions, type CreateCollectionOptionsWithSchemaType, type CreateCollectionOptionsWithTypedSchema, DataLoader, type DeleteMany, type DeleteOne, type DistinctDocumentId, type DocumentWithId, ENCRYPTION_ALGORITHMS, type EstimatedDocumentCount, type Find, type FindCursor, type FindOne, type FindOneAndUpdate, type FindOneAndUpdateUpdateOptions, type InferIdType, type InferSchemaTypeWithId, type InitItem, type InsertAndFind, type InsertMany, type InsertManyOptions, type InsertOne, type InsertOptions, type ModelClassBase, type ModelToMongoSelector, MongoCollection, type MongoFilter, type MongoSelector, type OptionalId, Repository, type SchemaWithRequiredId, type TypedId, type UpdateAndFind, type UpdateItem, type UpdateMany, type UpdateOne, type UpdateOptions, type Upsert, allConnectionPromises, collectionsRegistry, configureConnection, connections, createCollection, createIndexesPromises, deleteAllUnusedIndexes, getDBName, getMergedIndexes, getMongoConnection, getOrCreateEncryptionKey, getRegisteredCollections, registerCollection, typedId };
package/dist/index.js CHANGED
@@ -74,9 +74,6 @@ var OrionMongoDatabaseWrapper = class {
74
74
  configTimeout;
75
75
  constructor(connectionName) {
76
76
  this.connectionName = connectionName;
77
- logger.info("New connection requested", {
78
- connectionName
79
- });
80
77
  this.connectionEvent.setMaxListeners(Number.POSITIVE_INFINITY);
81
78
  this.connectionPromise = new Promise((resolve, reject) => {
82
79
  if (this.state === "connected") {
@@ -122,11 +119,8 @@ var OrionMongoDatabaseWrapper = class {
122
119
  return this;
123
120
  }
124
121
  this.state = "connecting";
125
- const censoredURI = this.uri.replace(/\/\/.*:.*@/, "//");
126
- logger.info("Connecting to mongo", {
127
- uri: censoredURI,
128
- connectionName: this.connectionName
129
- });
122
+ const censoredURI = this.uri.replace(/\/\/.*:.*@/, "//").replace(/^mongodb(\+srv)?:\/\//, "");
123
+ logger.info(`Starting MongoDB connection "${this.connectionName}" [${censoredURI}]`);
130
124
  if (this.encrypted.client) {
131
125
  await this.connectWithRetry(this.encrypted.client);
132
126
  logger.info("Successfully connected to encrypted mongo", {
@@ -137,10 +131,6 @@ var OrionMongoDatabaseWrapper = class {
137
131
  await this.connectWithRetry(this.client);
138
132
  this.state = "connected";
139
133
  this.connectionEvent.emit("connected", this.client);
140
- logger.info("Successfully connected to mongo", {
141
- uri: censoredURI,
142
- connectionName: this.connectionName
143
- });
144
134
  nextTick(() => {
145
135
  this.connectionEvent.removeAllListeners();
146
136
  this.connectionEvent = null;
@@ -1146,7 +1136,7 @@ var generateId_default = getIdGenerator;
1146
1136
 
1147
1137
  // src/createCollection/createIndexes.ts
1148
1138
  import { MongoExpiredSessionError, MongoNotConnectedError } from "mongodb";
1149
- import { logger as logger3 } from "@orion-js/logger";
1139
+ import { logger as logger4 } from "@orion-js/logger";
1150
1140
 
1151
1141
  // src/createCollection/deleteUnusedIndexes.ts
1152
1142
  import { logger as logger2 } from "@orion-js/logger";
@@ -1168,6 +1158,15 @@ function getIndexName(indexDef) {
1168
1158
  }
1169
1159
 
1170
1160
  // src/createCollection/deleteUnusedIndexes.ts
1161
+ function isTextIndexDefinition(keys) {
1162
+ return Object.values(keys).some((value) => value === "text");
1163
+ }
1164
+ function isMongoDBTextIndex(key) {
1165
+ return "_fts" in key && "_ftsx" in key;
1166
+ }
1167
+ function generateIndexName(keys) {
1168
+ return Object.entries(keys).map(([field, value]) => `${field}_${value}`).join("_");
1169
+ }
1171
1170
  function keysMatch(definitionKeys, currentIndexKey) {
1172
1171
  const defEntries = Object.entries(definitionKeys);
1173
1172
  const curEntries = Object.entries(currentIndexKey);
@@ -1183,7 +1182,12 @@ function isIndexDefined(definedIndexes, currentIndex) {
1183
1182
  return definedIndexes.some((defIndex) => {
1184
1183
  const customName = getIndexName(defIndex);
1185
1184
  if (customName && customName === currentIndex.name) return true;
1186
- return keysMatch(defIndex.keys, currentIndex.key);
1185
+ const defKeys = defIndex.keys;
1186
+ if (isTextIndexDefinition(defKeys) && isMongoDBTextIndex(currentIndex.key)) {
1187
+ const expectedName = generateIndexName(defKeys);
1188
+ return currentIndex.name === expectedName;
1189
+ }
1190
+ return keysMatch(defKeys, currentIndex.key);
1187
1191
  });
1188
1192
  }
1189
1193
  async function deleteUnusedIndexes(collection) {
@@ -1221,67 +1225,8 @@ async function deleteUnusedIndexes(collection) {
1221
1225
  return result;
1222
1226
  }
1223
1227
 
1224
- // src/createCollection/createIndexes.ts
1225
- async function checkIndexes(collection) {
1226
- await collection.connectionPromise;
1227
- let currentIndexes = [];
1228
- try {
1229
- currentIndexes = await collection.rawCollection.indexes();
1230
- } catch (error) {
1231
- if (error.codeName !== "NamespaceNotFound") throw error;
1232
- return;
1233
- }
1234
- if (!collection.indexes || collection.indexes.length === 0) {
1235
- return;
1236
- }
1237
- const unexpectedIndexes = currentIndexes.filter(
1238
- (index) => index.name !== "_id_" && !isIndexDefined(collection.indexes, index)
1239
- );
1240
- if (unexpectedIndexes.length > 0) {
1241
- logger3.warn(
1242
- `${unexpectedIndexes.length} unexpected indexes found in collection "${collection.name}": ${unexpectedIndexes.map((i) => i.name).join(", ")} | Delete the index or fix the collection definition`
1243
- );
1244
- }
1245
- }
1246
- async function loadIndexes(collection) {
1247
- if (!collection.indexes) return;
1248
- if (!collection.indexes.length) return;
1249
- await collection.connectionPromise;
1250
- const results = Promise.all(
1251
- collection.indexes.map(async (indexDef) => {
1252
- const { keys } = indexDef;
1253
- const options = getIndexOptions(indexDef);
1254
- try {
1255
- return await collection.rawCollection.createIndex(keys, options);
1256
- } catch (error) {
1257
- if (error.code === 85 || error.code === 86) {
1258
- console.info("Will delete index to create the new version");
1259
- const indexName = (() => {
1260
- const message = error.errorResponse.errmsg;
1261
- const indexName2 = message.split('name: "')[1].split('"')[0];
1262
- return indexName2;
1263
- })();
1264
- await collection.rawCollection.dropIndex(indexName);
1265
- console.info("Index was deleted, creating new index");
1266
- const result = await collection.rawCollection.createIndex(keys, options);
1267
- console.info("Index updated correctly");
1268
- return result;
1269
- }
1270
- if (error instanceof MongoExpiredSessionError || error instanceof MongoNotConnectedError) {
1271
- } else {
1272
- console.error(`Error creating index for collection ${collection.name}: ${error.message}`);
1273
- console.error(error);
1274
- return error.message;
1275
- }
1276
- }
1277
- })
1278
- );
1279
- await checkIndexes(collection);
1280
- return results;
1281
- }
1282
-
1283
1228
  // src/createCollection/collectionsRegistry.ts
1284
- import { logger as logger4 } from "@orion-js/logger";
1229
+ import { logger as logger3 } from "@orion-js/logger";
1285
1230
  var collectionsRegistry = /* @__PURE__ */ new Map();
1286
1231
  function indexesAreEqual(indexA, indexB) {
1287
1232
  const nameA = getIndexName(indexA);
@@ -1323,17 +1268,28 @@ function getRegisteredCollections(connectionName = "main") {
1323
1268
  }
1324
1269
  return Array.from(connectionCollections.values());
1325
1270
  }
1271
+ function getMergedIndexes(connectionName, collectionName) {
1272
+ const connectionCollections = collectionsRegistry.get(connectionName);
1273
+ if (!connectionCollections) {
1274
+ return [];
1275
+ }
1276
+ const collection = connectionCollections.get(collectionName);
1277
+ if (!collection) {
1278
+ return [];
1279
+ }
1280
+ return collection.indexes || [];
1281
+ }
1326
1282
  async function deleteAllUnusedIndexes(connectionName = "main") {
1327
1283
  const collections = getRegisteredCollections(connectionName);
1328
1284
  if (collections.length === 0) {
1329
- logger4.warn(`No collections registered for connection "${connectionName}"`);
1285
+ logger3.warn(`No collections registered for connection "${connectionName}"`);
1330
1286
  return [];
1331
1287
  }
1332
1288
  if (createIndexesPromises.length > 0) {
1333
- logger4.info("Waiting for pending index creation to complete before deleting unused indexes...");
1289
+ logger3.info("Waiting for pending index creation to complete before deleting unused indexes...");
1334
1290
  await Promise.all(createIndexesPromises);
1335
1291
  }
1336
- logger4.info(
1292
+ logger3.info(
1337
1293
  `Deleting unused indexes from ${collections.length} collections on connection "${connectionName}"`
1338
1294
  );
1339
1295
  const results = [];
@@ -1344,7 +1300,67 @@ async function deleteAllUnusedIndexes(connectionName = "main") {
1344
1300
  }
1345
1301
  }
1346
1302
  const totalDeleted = results.reduce((sum, r) => sum + r.deletedIndexes.length, 0);
1347
- logger4.info(`Deleted ${totalDeleted} unused indexes from ${results.length} collections`);
1303
+ logger3.info(`Deleted ${totalDeleted} unused indexes from ${results.length} collections`);
1304
+ return results;
1305
+ }
1306
+
1307
+ // src/createCollection/createIndexes.ts
1308
+ async function checkIndexes(collection) {
1309
+ await collection.connectionPromise;
1310
+ let currentIndexes = [];
1311
+ try {
1312
+ currentIndexes = await collection.rawCollection.indexes();
1313
+ } catch (error) {
1314
+ if (error.codeName !== "NamespaceNotFound") throw error;
1315
+ return;
1316
+ }
1317
+ const mergedIndexes = getMergedIndexes(collection.connectionName, collection.name);
1318
+ if (mergedIndexes.length === 0) {
1319
+ return;
1320
+ }
1321
+ const unexpectedIndexes = currentIndexes.filter(
1322
+ (index) => index.name !== "_id_" && !isIndexDefined(mergedIndexes, index)
1323
+ );
1324
+ if (unexpectedIndexes.length > 0) {
1325
+ logger4.warn(
1326
+ `${unexpectedIndexes.length} unexpected indexes found in collection "${collection.name}": ${unexpectedIndexes.map((i) => i.name).join(", ")} | Delete the index or fix the collection definition`
1327
+ );
1328
+ }
1329
+ }
1330
+ async function loadIndexes(collection) {
1331
+ if (!collection.indexes) return;
1332
+ if (!collection.indexes.length) return;
1333
+ await collection.connectionPromise;
1334
+ const results = Promise.all(
1335
+ collection.indexes.map(async (indexDef) => {
1336
+ const { keys } = indexDef;
1337
+ const options = getIndexOptions(indexDef);
1338
+ try {
1339
+ return await collection.rawCollection.createIndex(keys, options);
1340
+ } catch (error) {
1341
+ if (error.code === 85 || error.code === 86) {
1342
+ console.info("Will delete index to create the new version");
1343
+ const indexName = (() => {
1344
+ const message = error.errorResponse.errmsg;
1345
+ const indexName2 = message.split('name: "')[1].split('"')[0];
1346
+ return indexName2;
1347
+ })();
1348
+ await collection.rawCollection.dropIndex(indexName);
1349
+ console.info("Index was deleted, creating new index");
1350
+ const result = await collection.rawCollection.createIndex(keys, options);
1351
+ console.info("Index updated correctly");
1352
+ return result;
1353
+ }
1354
+ if (error instanceof MongoExpiredSessionError || error instanceof MongoNotConnectedError) {
1355
+ } else {
1356
+ console.error(`Error creating index for collection ${collection.name}: ${error.message}`);
1357
+ console.error(error);
1358
+ return error.message;
1359
+ }
1360
+ }
1361
+ })
1362
+ );
1363
+ await checkIndexes(collection);
1348
1364
  return results;
1349
1365
  }
1350
1366
 
@@ -1628,6 +1644,7 @@ export {
1628
1644
  createIndexesPromises,
1629
1645
  deleteAllUnusedIndexes,
1630
1646
  getDBName,
1647
+ getMergedIndexes,
1631
1648
  getMongoConnection,
1632
1649
  getOrCreateEncryptionKey,
1633
1650
  getRegisteredCollections,