diff --git a/src/collection.ts b/src/collection.ts index 8fcdf90bff9..4d021ecc01a 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -52,7 +52,8 @@ import type { CreateIndexesOptions, DropIndexesOptions, IndexDescription, - IndexDirection, + IndexDescriptionCompact, + IndexDescriptionInfo, IndexInformationOptions, IndexSpecification, ListIndexesOptions @@ -693,8 +694,23 @@ export class Collection { * * @param options - Optional settings for the command */ - async indexInformation(options?: IndexInformationOptions): Promise { - return await this.indexes({ ...options, full: options?.full ?? false }); + indexInformation( + options: IndexInformationOptions & { full: true } + ): Promise; + indexInformation( + options: IndexInformationOptions & { full?: false } + ): Promise; + indexInformation( + options: IndexInformationOptions + ): Promise; + indexInformation(): Promise; + async indexInformation( + options?: IndexInformationOptions + ): Promise { + return await this.indexes({ + ...options, + full: options?.full ?? false + }); } /** @@ -798,19 +814,25 @@ export class Collection { * * @param options - Optional settings for the command */ - async indexes(options?: IndexInformationOptions): Promise { - const indexes = await this.listIndexes(options).toArray(); + indexes(options: IndexInformationOptions & { full?: true }): Promise; + indexes(options: IndexInformationOptions & { full: false }): Promise; + indexes( + options: IndexInformationOptions + ): Promise; + indexes(options?: ListIndexesOptions): Promise; + async indexes( + options?: IndexInformationOptions + ): Promise { + const indexes: IndexDescriptionInfo[] = await this.listIndexes(options).toArray(); const full = options?.full ?? true; if (full) { return indexes; } - const object: Record< - string, - Array<[name: string, direction: IndexDirection]> - > = Object.fromEntries(indexes.map(({ name, key }) => [name, Object.entries(key)])); + const object: IndexDescriptionCompact = Object.fromEntries( + indexes.map(({ name, key }) => [name, Object.entries(key)]) + ); - // @ts-expect-error TODO(NODE-6029): fix return type of `indexes()` and `indexInformation()` return object; } diff --git a/src/db.ts b/src/db.ts index 1dda4834c2e..abb068f5db6 100644 --- a/src/db.ts +++ b/src/db.ts @@ -25,6 +25,8 @@ import { executeOperation } from './operations/execute_operation'; import { CreateIndexesOperation, type CreateIndexesOptions, + type IndexDescriptionCompact, + type IndexDescriptionInfo, type IndexInformationOptions, type IndexSpecification } from './operations/indexes'; @@ -482,7 +484,23 @@ export class Db { * @param name - The name of the collection. * @param options - Optional settings for the command */ - async indexInformation(name: string, options?: IndexInformationOptions): Promise { + indexInformation( + name: string, + options: IndexInformationOptions & { full: true } + ): Promise; + indexInformation( + name: string, + options: IndexInformationOptions & { full?: false } + ): Promise; + indexInformation( + name: string, + options: IndexInformationOptions + ): Promise; + indexInformation(name: string): Promise; + async indexInformation( + name: string, + options?: IndexInformationOptions + ): Promise { return await this.collection(name).indexInformation(resolveOptions(this, options)); } diff --git a/src/index.ts b/src/index.ts index 795f6835c8c..f9188d5952c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -471,6 +471,8 @@ export type { CreateIndexesOptions, DropIndexesOptions, IndexDescription, + IndexDescriptionCompact, + IndexDescriptionInfo, IndexDirection, IndexSpecification, ListIndexesOptions diff --git a/src/operations/indexes.ts b/src/operations/indexes.ts index e32ccfae182..8bf390f28b7 100644 --- a/src/operations/indexes.ts +++ b/src/operations/indexes.ts @@ -214,6 +214,18 @@ function resolveIndexDescription( ); } +/** + * @public + * The index information returned by the listIndexes command. https://www.mongodb.com/docs/manual/reference/command/listIndexes/#mongodb-dbcommand-dbcmd.listIndexes + */ +export type IndexDescriptionInfo = Omit & { + key: { [key: string]: IndexDirection }; + v?: IndexDescription['version']; +} & Document; + +/** @public */ +export type IndexDescriptionCompact = Record; + /** * @internal * diff --git a/test/types/indexes_test-d.ts b/test/types/indexes_test-d.ts index 7cca9d71062..8d68a34f30f 100644 --- a/test/types/indexes_test-d.ts +++ b/test/types/indexes_test-d.ts @@ -1,16 +1,99 @@ -import { expectType } from 'tsd'; +import { expectAssignable, expectType } from 'tsd'; -import { type Document, MongoClient } from '../../src'; +import { type IndexInformationOptions, MongoClient } from '../../src'; +import { type IndexDescriptionCompact, type IndexDescriptionInfo } from '../mongodb'; const client = new MongoClient(''); const db = client.db('test'); const collection = db.collection('test.find'); -// Promise variant testing -expectType>(collection.indexes()); -expectType>(collection.indexes({})); +const exampleFullIndexes: IndexDescriptionInfo[] = [ + { v: 2, key: { _id: 1 }, name: '_id_' }, + { v: 2, key: { listingName: 'hashed' }, name: 'listingName_hashed' }, + { + v: 2, + key: { 'auctionDetails.listingId': 1 }, + name: 'auctionDetails_listingId_1', + unique: true + } +]; +const exampleCompactIndexes: IndexDescriptionCompact = { + _id_: [['_id', 1]], + listingName_hashed: [['listingName', 'hashed']], + auctionDetails_listingId_1: [['auctionDetails.listingId', 1]] +}; + +const ambiguousFullness = Math.random() > 0.5; + +// test Collection.prototype.indexes + +const defaultIndexes = await collection.indexes(); +const emptyOptionsIndexes = await collection.indexes({}); +const fullIndexes = await collection.indexes({ full: true }); +const notFullIndexes = await collection.indexes({ full: false }); +const ambiguousIndexes = await collection.indexes({ full: ambiguousFullness }); + +expectAssignable(exampleFullIndexes); +expectAssignable(exampleFullIndexes); +expectAssignable(exampleCompactIndexes); +expectAssignable(exampleCompactIndexes); + +expectType(defaultIndexes); +expectType(emptyOptionsIndexes); +expectType(fullIndexes); +expectType(notFullIndexes); +expectType(ambiguousIndexes); + +// test Collection.prototype.indexInformation + +const defaultIndexInfo = await collection.indexInformation(); +const emptyOptionsIndexInfo = await collection.indexInformation({}); +const fullIndexInfo = await collection.indexInformation({ full: true }); +const notFullIndexInfo = await collection.indexInformation({ full: false }); +const ambiguousIndexInfo = await collection.indexInformation({ full: ambiguousFullness }); + +expectAssignable(exampleFullIndexes); +expectAssignable(exampleFullIndexes); +expectAssignable(exampleCompactIndexes); +expectAssignable(exampleCompactIndexes); + +expectType(defaultIndexInfo); +expectType(emptyOptionsIndexInfo); +expectType(fullIndexInfo); +expectType(notFullIndexInfo); +expectType(ambiguousIndexInfo); // Explicit check for iterable result for (const index of await collection.indexes()) { - expectType(index); + expectType(index); } + +// test Db.prototype.indexInformation + +const dbDefaultIndexInfo = await db.indexInformation('some-collection'); +const dbEmptyOptionsIndexInfo = await db.indexInformation('some-collection', {}); +const dbFullIndexInfo = await db.indexInformation('some-collection', { full: true }); +const dbNotFullIndexInfo = await db.indexInformation('some-collection', { full: false }); +const dbAmbiguousIndexInfo = await db.indexInformation('some-collection', { + full: ambiguousFullness +}); + +expectAssignable(exampleFullIndexes); +expectAssignable(exampleFullIndexes); +expectAssignable(exampleCompactIndexes); + +expectType(dbDefaultIndexInfo); +expectType(dbEmptyOptionsIndexInfo); +expectType(dbFullIndexInfo); +expectType(dbNotFullIndexInfo); +expectType(dbAmbiguousIndexInfo); + +// test indexInformation with non-literal options +const options: IndexInformationOptions = {}; +const indexInfo = await db.collection('some-collection').indexInformation(options); +const indexes = await db.collection('some-collection').indexes(options); +const indexDbInfo = await db.indexInformation('some-collection', options); + +expectType(indexInfo); +expectType(indexes); +expectType(indexDbInfo);