@@ -169,10 +169,11 @@ function isSingleIndexTuple(t: unknown): t is [string, IndexDirection] {
169
169
return Array . isArray ( t ) && t . length === 2 && isIndexDirection ( t [ 1 ] ) ;
170
170
}
171
171
172
- function makeIndexSpec (
173
- indexSpec : IndexSpecification ,
174
- options ?: CreateIndexesOptions
175
- ) : IndexDescription {
172
+ /**
173
+ * Converts an `IndexSpecification`, which can be specified in multiple formats, into a
174
+ * valid `key` for the createIndexes command.
175
+ */
176
+ function constructIndexDescriptionMap ( indexSpec : IndexSpecification ) : Map < string , IndexDirection > {
176
177
const key : Map < string , IndexDirection > = new Map ( ) ;
177
178
178
179
const indexSpecs =
@@ -195,14 +196,46 @@ function makeIndexSpec(
195
196
}
196
197
}
197
198
198
- return { ... options , key } ;
199
+ return key ;
199
200
}
200
201
202
+ /**
203
+ * Receives an index description and returns a modified index description which has had invalid options removed
204
+ * from the description and has mapped the `version` option to the `v` option.
205
+ */
206
+ function resolveIndexDescription (
207
+ description : IndexDescription
208
+ ) : Omit < ResolvedIndexDescription , 'key' > {
209
+ const validProvidedOptions = Object . entries ( { ...description } ) . filter ( ( [ optionName ] ) =>
210
+ VALID_INDEX_OPTIONS . has ( optionName )
211
+ ) ;
212
+
213
+ return Object . fromEntries (
214
+ // we support the `version` option, but the `createIndexes` command expects it to be the `v`
215
+ validProvidedOptions . map ( ( [ name , value ] ) => ( name === 'version' ? [ 'v' , value ] : [ name , value ] ) )
216
+ ) ;
217
+ }
218
+
219
+ /**
220
+ * @internal
221
+ *
222
+ * Internally, the driver represents index description keys with `Map`s to preserve key ordering.
223
+ * We don't require users to specify maps, so we transform user provided descriptions into
224
+ * "resolved" by converting the `key` into a JS `Map`, if it isn't already a map.
225
+ *
226
+ * Additionally, we support the `version` option, but the `createIndexes` command uses the field `v`
227
+ * to specify the index version so we map the value of `version` to `v`, if provided.
228
+ */
229
+ type ResolvedIndexDescription = Omit < IndexDescription , 'key' | 'version' > & {
230
+ key : Map < string , IndexDirection > ;
231
+ v ?: IndexDescription [ 'version' ] ;
232
+ } ;
233
+
201
234
/** @internal */
202
235
export class CreateIndexesOperation extends CommandOperation < string [ ] > {
203
236
override options : CreateIndexesOptions ;
204
237
collectionName : string ;
205
- indexes : ReadonlyArray < Omit < IndexDescription , 'key' > & { key : Map < string , IndexDirection > } > ;
238
+ indexes : ReadonlyArray < ResolvedIndexDescription > ;
206
239
207
240
private constructor (
208
241
parent : OperationParent ,
@@ -214,16 +247,12 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
214
247
215
248
this . options = options ?? { } ;
216
249
this . collectionName = collectionName ;
217
- this . indexes = indexes . map ( userIndex => {
250
+ this . indexes = indexes . map ( ( userIndex : IndexDescription ) : ResolvedIndexDescription => {
218
251
// Ensure the key is a Map to preserve index key ordering
219
252
const key =
220
253
userIndex . key instanceof Map ? userIndex . key : new Map ( Object . entries ( userIndex . key ) ) ;
221
254
const name = userIndex . name != null ? userIndex . name : Array . from ( key ) . flat ( ) . join ( '_' ) ;
222
- const validIndexOptions = Object . fromEntries (
223
- Object . entries ( { ...userIndex } ) . filter ( ( [ optionName ] ) =>
224
- VALID_INDEX_OPTIONS . has ( optionName )
225
- )
226
- ) ;
255
+ const validIndexOptions = resolveIndexDescription ( userIndex ) ;
227
256
return {
228
257
...validIndexOptions ,
229
258
name,
@@ -245,14 +274,11 @@ export class CreateIndexesOperation extends CommandOperation<string[]> {
245
274
parent : OperationParent ,
246
275
collectionName : string ,
247
276
indexSpec : IndexSpecification ,
248
- options ? : CreateIndexesOptions
277
+ options : CreateIndexesOptions = { }
249
278
) : CreateIndexesOperation {
250
- return new CreateIndexesOperation (
251
- parent ,
252
- collectionName ,
253
- [ makeIndexSpec ( indexSpec , options ) ] ,
254
- options
255
- ) ;
279
+ const key = constructIndexDescriptionMap ( indexSpec ) ;
280
+ const description : IndexDescription = { ...options , key } ;
281
+ return new CreateIndexesOperation ( parent , collectionName , [ description ] , options ) ;
256
282
}
257
283
258
284
override get commandName ( ) {
0 commit comments