@orion-js/mongodb 4.2.0 → 4.2.3

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
@@ -304,6 +304,65 @@ declare function createCollection<T extends TypedSchemaOnSchema & {
304
304
  }>(options: CreateCollectionOptionsWithTypedSchema<T>): Collection<InferSchemaType<T>>;
305
305
  declare function createCollection<T extends ModelClassBase>(options: CreateCollectionOptions<T>): Collection<T>;
306
306
 
307
+ /**
308
+ * Result of the deleteUnusedIndexes operation
309
+ */
310
+ interface DeleteUnusedIndexesResult {
311
+ /** Names of the indexes that were deleted */
312
+ deletedIndexes: string[];
313
+ /** Name of the collection that was cleaned */
314
+ collectionName: string;
315
+ }
316
+
317
+ /**
318
+ * Registry that tracks all collections created via createCollection().
319
+ * Maps connection name to a map of collection name to collection instance.
320
+ * When the same collection is registered multiple times, indexes are merged.
321
+ */
322
+ declare const collectionsRegistry: Map<string, Map<string, Collection<ModelClassBase>>>;
323
+ /**
324
+ * Registers a collection in the registry.
325
+ * Called automatically when a collection is created via createCollection().
326
+ * If the same collection name is registered multiple times, indexes are merged
327
+ * to support multiple createCollection() calls for the same collection.
328
+ * @param connectionName - The name of the MongoDB connection
329
+ * @param collection - The collection instance to register
330
+ */
331
+ declare function registerCollection(connectionName: string, collection: Collection<ModelClassBase>): void;
332
+ /**
333
+ * Gets all registered collections for a specific connection.
334
+ * @param connectionName - The name of the MongoDB connection (defaults to 'main')
335
+ * @returns Array of registered collections for the connection
336
+ */
337
+ declare function getRegisteredCollections(connectionName?: string): Array<Collection<ModelClassBase>>;
338
+ /**
339
+ * Deletes unused indexes from all registered collections for a connection.
340
+ * Iterates over all collections registered via createCollection() and
341
+ * removes indexes that exist in MongoDB but are not defined in the collection configuration.
342
+ *
343
+ * **Important**: This function waits for all pending index creation to complete before
344
+ * deleting any indexes, to avoid race conditions where an index being created might
345
+ * be incorrectly identified as unused.
346
+ *
347
+ * @param connectionName - The name of the MongoDB connection (defaults to 'main')
348
+ * @returns Array of results for each collection that had indexes deleted
349
+ *
350
+ * @example
351
+ * ```ts
352
+ * // Delete unused indexes from all collections on the main connection
353
+ * const results = await deleteAllUnusedIndexes()
354
+ *
355
+ * // Delete unused indexes from all collections on a specific connection
356
+ * const results = await deleteAllUnusedIndexes('secondary')
357
+ *
358
+ * // Log results
359
+ * for (const result of results) {
360
+ * console.log(`${result.collectionName}: deleted ${result.deletedIndexes.length} indexes`)
361
+ * }
362
+ * ```
363
+ */
364
+ declare function deleteAllUnusedIndexes(connectionName?: string): Promise<DeleteUnusedIndexesResult[]>;
365
+
307
366
  declare function getOrCreateEncryptionKey({ keyAltName, kmsProvider, masterKey, connectionName, keyVaultDatabase, keyVaultCollection, kmsProviders, }: {
308
367
  keyAltName: string;
309
368
  kmsProvider: keyof KMSProviders;
@@ -321,4 +380,4 @@ declare const ENCRYPTION_ALGORITHMS: {
321
380
  RANDOM: string;
322
381
  };
323
382
 
324
- 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, configureConnection, connections, createCollection, createIndexesPromises, getDBName, getMongoConnection, getOrCreateEncryptionKey, typedId };
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 };
package/dist/index.d.ts CHANGED
@@ -304,6 +304,65 @@ declare function createCollection<T extends TypedSchemaOnSchema & {
304
304
  }>(options: CreateCollectionOptionsWithTypedSchema<T>): Collection<InferSchemaType<T>>;
305
305
  declare function createCollection<T extends ModelClassBase>(options: CreateCollectionOptions<T>): Collection<T>;
306
306
 
307
+ /**
308
+ * Result of the deleteUnusedIndexes operation
309
+ */
310
+ interface DeleteUnusedIndexesResult {
311
+ /** Names of the indexes that were deleted */
312
+ deletedIndexes: string[];
313
+ /** Name of the collection that was cleaned */
314
+ collectionName: string;
315
+ }
316
+
317
+ /**
318
+ * Registry that tracks all collections created via createCollection().
319
+ * Maps connection name to a map of collection name to collection instance.
320
+ * When the same collection is registered multiple times, indexes are merged.
321
+ */
322
+ declare const collectionsRegistry: Map<string, Map<string, Collection<ModelClassBase>>>;
323
+ /**
324
+ * Registers a collection in the registry.
325
+ * Called automatically when a collection is created via createCollection().
326
+ * If the same collection name is registered multiple times, indexes are merged
327
+ * to support multiple createCollection() calls for the same collection.
328
+ * @param connectionName - The name of the MongoDB connection
329
+ * @param collection - The collection instance to register
330
+ */
331
+ declare function registerCollection(connectionName: string, collection: Collection<ModelClassBase>): void;
332
+ /**
333
+ * Gets all registered collections for a specific connection.
334
+ * @param connectionName - The name of the MongoDB connection (defaults to 'main')
335
+ * @returns Array of registered collections for the connection
336
+ */
337
+ declare function getRegisteredCollections(connectionName?: string): Array<Collection<ModelClassBase>>;
338
+ /**
339
+ * Deletes unused indexes from all registered collections for a connection.
340
+ * Iterates over all collections registered via createCollection() and
341
+ * removes indexes that exist in MongoDB but are not defined in the collection configuration.
342
+ *
343
+ * **Important**: This function waits for all pending index creation to complete before
344
+ * deleting any indexes, to avoid race conditions where an index being created might
345
+ * be incorrectly identified as unused.
346
+ *
347
+ * @param connectionName - The name of the MongoDB connection (defaults to 'main')
348
+ * @returns Array of results for each collection that had indexes deleted
349
+ *
350
+ * @example
351
+ * ```ts
352
+ * // Delete unused indexes from all collections on the main connection
353
+ * const results = await deleteAllUnusedIndexes()
354
+ *
355
+ * // Delete unused indexes from all collections on a specific connection
356
+ * const results = await deleteAllUnusedIndexes('secondary')
357
+ *
358
+ * // Log results
359
+ * for (const result of results) {
360
+ * console.log(`${result.collectionName}: deleted ${result.deletedIndexes.length} indexes`)
361
+ * }
362
+ * ```
363
+ */
364
+ declare function deleteAllUnusedIndexes(connectionName?: string): Promise<DeleteUnusedIndexesResult[]>;
365
+
307
366
  declare function getOrCreateEncryptionKey({ keyAltName, kmsProvider, masterKey, connectionName, keyVaultDatabase, keyVaultCollection, kmsProviders, }: {
308
367
  keyAltName: string;
309
368
  kmsProvider: keyof KMSProviders;
@@ -321,4 +380,4 @@ declare const ENCRYPTION_ALGORITHMS: {
321
380
  RANDOM: string;
322
381
  };
323
382
 
324
- 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, configureConnection, connections, createCollection, createIndexesPromises, getDBName, getMongoConnection, getOrCreateEncryptionKey, typedId };
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 };
package/dist/index.js CHANGED
@@ -1280,6 +1280,74 @@ async function loadIndexes(collection) {
1280
1280
  return results;
1281
1281
  }
1282
1282
 
1283
+ // src/createCollection/collectionsRegistry.ts
1284
+ import { logger as logger4 } from "@orion-js/logger";
1285
+ var collectionsRegistry = /* @__PURE__ */ new Map();
1286
+ function indexesAreEqual(indexA, indexB) {
1287
+ const nameA = getIndexName(indexA);
1288
+ const nameB = getIndexName(indexB);
1289
+ if (nameA && nameB) {
1290
+ return nameA === nameB;
1291
+ }
1292
+ return keysMatch(
1293
+ indexA.keys,
1294
+ indexB.keys
1295
+ );
1296
+ }
1297
+ function mergeIndexes(existingIndexes, newIndexes) {
1298
+ const merged = [...existingIndexes];
1299
+ for (const newIndex of newIndexes) {
1300
+ const isDuplicate = existingIndexes.some((existing) => indexesAreEqual(existing, newIndex));
1301
+ if (!isDuplicate) {
1302
+ merged.push(newIndex);
1303
+ }
1304
+ }
1305
+ return merged;
1306
+ }
1307
+ function registerCollection(connectionName, collection) {
1308
+ if (!collectionsRegistry.has(connectionName)) {
1309
+ collectionsRegistry.set(connectionName, /* @__PURE__ */ new Map());
1310
+ }
1311
+ const connectionMap = collectionsRegistry.get(connectionName);
1312
+ const existingCollection = connectionMap.get(collection.name);
1313
+ if (existingCollection) {
1314
+ existingCollection.indexes = mergeIndexes(existingCollection.indexes, collection.indexes);
1315
+ } else {
1316
+ connectionMap.set(collection.name, collection);
1317
+ }
1318
+ }
1319
+ function getRegisteredCollections(connectionName = "main") {
1320
+ const connectionCollections = collectionsRegistry.get(connectionName);
1321
+ if (!connectionCollections) {
1322
+ return [];
1323
+ }
1324
+ return Array.from(connectionCollections.values());
1325
+ }
1326
+ async function deleteAllUnusedIndexes(connectionName = "main") {
1327
+ const collections = getRegisteredCollections(connectionName);
1328
+ if (collections.length === 0) {
1329
+ logger4.warn(`No collections registered for connection "${connectionName}"`);
1330
+ return [];
1331
+ }
1332
+ if (createIndexesPromises.length > 0) {
1333
+ logger4.info("Waiting for pending index creation to complete before deleting unused indexes...");
1334
+ await Promise.all(createIndexesPromises);
1335
+ }
1336
+ logger4.info(
1337
+ `Deleting unused indexes from ${collections.length} collections on connection "${connectionName}"`
1338
+ );
1339
+ const results = [];
1340
+ for (const collection of collections) {
1341
+ const result = await collection.deleteUnusedIndexes();
1342
+ if (result.deletedIndexes.length > 0) {
1343
+ results.push(result);
1344
+ }
1345
+ }
1346
+ const totalDeleted = results.reduce((sum, r) => sum + r.deletedIndexes.length, 0);
1347
+ logger4.info(`Deleted ${totalDeleted} unused indexes from ${results.length} collections`);
1348
+ return results;
1349
+ }
1350
+
1283
1351
  // src/createCollection/getSchemaAndModel.ts
1284
1352
  import { clone as clone3 } from "@orion-js/helpers";
1285
1353
  Symbol.metadata ?? (Symbol.metadata = Symbol("Symbol.metadata"));
@@ -1312,7 +1380,7 @@ function getSchema(options) {
1312
1380
  }
1313
1381
 
1314
1382
  // src/createCollection/wrapMethods.ts
1315
- import { logger as logger4 } from "@orion-js/logger";
1383
+ import { logger as logger5 } from "@orion-js/logger";
1316
1384
  function wrapMethods(collection) {
1317
1385
  const methodsWithPromises = [
1318
1386
  "findOne",
@@ -1348,7 +1416,7 @@ function wrapMethods(collection) {
1348
1416
  collection[methodName2] = (...args) => {
1349
1417
  collection.startConnection();
1350
1418
  if (!collection.rawCollection) {
1351
- logger4.error("Method called before connection was initialized", {
1419
+ logger5.error("Method called before connection was initialized", {
1352
1420
  collectionName: collection.name,
1353
1421
  connectionName: collection.connectionName,
1354
1422
  methodName: methodName2
@@ -1458,6 +1526,7 @@ function createCollection(options) {
1458
1526
  }
1459
1527
  wrapMethods(mainCollection);
1460
1528
  wrapMethods(encryptedCollection);
1529
+ registerCollection(connectionName, mainCollection);
1461
1530
  return mainCollection;
1462
1531
  }
1463
1532
 
@@ -1488,7 +1557,7 @@ function MongoCollection(options) {
1488
1557
  }
1489
1558
 
1490
1559
  // src/encrypted/getOrCreateEncryptionKey.ts
1491
- import { logger as logger5 } from "@orion-js/logger";
1560
+ import { logger as logger6 } from "@orion-js/logger";
1492
1561
  import { ClientEncryption, MongoClient as MongoClient2 } from "mongodb";
1493
1562
  async function getOrCreateEncryptionKey({
1494
1563
  keyAltName,
@@ -1500,7 +1569,7 @@ async function getOrCreateEncryptionKey({
1500
1569
  kmsProviders
1501
1570
  }) {
1502
1571
  const keyVaultNamespace = `${keyVaultDatabase}.${keyVaultCollection}`;
1503
- logger5.info("Connecting to database to get or create the encryption key", {
1572
+ logger6.info("Connecting to database to get or create the encryption key", {
1504
1573
  keyVaultNamespace,
1505
1574
  keyAltName
1506
1575
  });
@@ -1518,14 +1587,14 @@ async function getOrCreateEncryptionKey({
1518
1587
  });
1519
1588
  const key = await clientEncryption.getKeyByAltName(keyAltName);
1520
1589
  if (key) {
1521
- logger5.info("Key found on the key vault", {
1590
+ logger6.info("Key found on the key vault", {
1522
1591
  keyVaultNamespace,
1523
1592
  keyAltName,
1524
1593
  UUID: key._id
1525
1594
  });
1526
1595
  return { key: key._id, keyVaultNamespace };
1527
1596
  }
1528
- logger5.info("Key not found on the key vault, creating a new one", {
1597
+ logger6.info("Key not found on the key vault, creating a new one", {
1529
1598
  keyVaultNamespace,
1530
1599
  keyAltName
1531
1600
  });
@@ -1533,7 +1602,7 @@ async function getOrCreateEncryptionKey({
1533
1602
  keyAltNames: [keyAltName],
1534
1603
  ...masterKey ? { masterKey } : {}
1535
1604
  });
1536
- logger5.info("New encryption key created", {
1605
+ logger6.info("New encryption key created", {
1537
1606
  keyVaultNamespace,
1538
1607
  keyAltName,
1539
1608
  UUID: newKey
@@ -1552,13 +1621,17 @@ export {
1552
1621
  MongoDB,
1553
1622
  Repository,
1554
1623
  allConnectionPromises,
1624
+ collectionsRegistry,
1555
1625
  configureConnection,
1556
1626
  connections,
1557
1627
  createCollection,
1558
1628
  createIndexesPromises,
1629
+ deleteAllUnusedIndexes,
1559
1630
  getDBName,
1560
1631
  getMongoConnection,
1561
1632
  getOrCreateEncryptionKey,
1633
+ getRegisteredCollections,
1634
+ registerCollection,
1562
1635
  typedId
1563
1636
  };
1564
1637
  //# sourceMappingURL=index.js.map