Skip to content

Commit 35964c8

Browse files
committed
fixups
1 parent 0c03cf7 commit 35964c8

File tree

4 files changed

+61
-61
lines changed

4 files changed

+61
-61
lines changed

src/operations/indexes.ts

+34-57
Original file line numberDiff line numberDiff line change
@@ -137,54 +137,39 @@ function isSingleIndexTuple(t: unknown): t is [string, IndexDirection] {
137137
return Array.isArray(t) && t.length === 2 && isIndexDirection(t[1]);
138138
}
139139

140-
function makeIndexSpec(indexSpec: IndexSpecification, options: any): IndexDescription {
141-
function getFieldHash(indexSpec: IndexSpecification) {
142-
const fieldHash: Map<string, IndexDirection> = new Map();
143-
144-
let indexSpecArr: IndexSpecification[];
145-
146-
// Wrap indexSpec in array if needed
147-
if (!Array.isArray(indexSpec) || isSingleIndexTuple(indexSpec)) {
148-
indexSpecArr = [indexSpec];
149-
} else {
150-
indexSpecArr = indexSpec;
151-
}
152-
153-
// Iterate through array and handle different types
154-
for (const spec of indexSpecArr) {
155-
if ('string' === typeof spec) {
156-
fieldHash.set(spec, 1);
157-
} else if (Array.isArray(spec)) {
158-
fieldHash.set(spec[0], spec[1] ?? 1);
159-
} else if (spec instanceof Map) {
160-
for (const [key, value] of spec) {
161-
fieldHash.set(key, value);
162-
}
163-
} else if (isObject(spec)) {
164-
for (const [key, value] of Object.entries(spec)) {
165-
fieldHash.set(key, value);
166-
}
140+
function makeIndexSpec(
141+
indexSpec: IndexSpecification,
142+
options?: CreateIndexesOptions
143+
): IndexDescription {
144+
const key: Map<string, IndexDirection> = new Map();
145+
146+
const indexSpecs =
147+
!Array.isArray(indexSpec) || isSingleIndexTuple(indexSpec) ? [indexSpec] : indexSpec;
148+
149+
// Iterate through array and handle different types
150+
for (const spec of indexSpecs) {
151+
if (typeof spec === 'string') {
152+
key.set(spec, 1);
153+
} else if (Array.isArray(spec)) {
154+
key.set(spec[0], spec[1] ?? 1);
155+
} else if (spec instanceof Map) {
156+
for (const [property, value] of spec) {
157+
key.set(property, value);
158+
}
159+
} else if (isObject(spec)) {
160+
for (const [property, value] of Object.entries(spec)) {
161+
key.set(property, value);
167162
}
168163
}
169-
return fieldHash;
170164
}
171165

172-
const fieldHash = getFieldHash(indexSpec);
173-
174-
// Generate the index name
175-
const name = typeof options.name === 'string' ? options.name : null;
176-
177166
// Set up the index
178-
const finalIndexSpec: Document = { name, key: fieldHash };
179-
180-
// merge valid index options into the index spec
181-
for (const optionName in options) {
182-
if (VALID_INDEX_OPTIONS.has(optionName)) {
183-
finalIndexSpec[optionName] = options[optionName];
184-
}
185-
}
186-
187-
return finalIndexSpec as IndexDescription;
167+
return {
168+
...Object.fromEntries(
169+
Object.entries({ ...options }).filter(([optionName]) => VALID_INDEX_OPTIONS.has(optionName))
170+
),
171+
key
172+
};
188173
}
189174

190175
/** @internal */
@@ -235,27 +220,24 @@ export class CreateIndexesOperation<
235220
this.collectionName = collectionName;
236221

237222
// Ensure we generate the correct name if the parameter is not set
238-
const normalizedIndexes = [];
223+
const namedIndexes = [];
239224
for (const userIndex of indexes) {
240-
const key =
241-
userIndex.key instanceof Map ? userIndex.key : new Map(Object.entries(userIndex.key));
242225
const index: Omit<IndexDescription, 'key'> & { key: Map<string, IndexDirection> } = {
243226
...userIndex,
244-
key
227+
// Ensure the key is a Map to preserve index key ordering
228+
key: userIndex.key instanceof Map ? userIndex.key : new Map(Object.entries(userIndex.key))
245229
};
246230
if (index.name == null) {
231+
// Ensure every index is named
247232
const keys = [];
248-
249233
for (const [name, direction] of index.key) {
250234
keys.push(`${name}_${direction}`);
251235
}
252-
253-
// Set the name
254236
index.name = keys.join('_');
255237
}
256-
normalizedIndexes.push(index);
238+
namedIndexes.push(index);
257239
}
258-
this.indexes = normalizedIndexes;
240+
this.indexes = namedIndexes;
259241
}
260242

261243
override execute(
@@ -318,11 +300,6 @@ export class CreateIndexOperation extends CreateIndexesOperation<string> {
318300
indexSpec: IndexSpecification,
319301
options?: CreateIndexesOptions
320302
) {
321-
// createIndex can be called with a variety of styles:
322-
// coll.createIndex('a');
323-
// coll.createIndex({ a: 1 });
324-
// coll.createIndex([['a', 1]]);
325-
// createIndexes is always called with an array of index spec objects
326303
super(parent, collectionName, [makeIndexSpec(indexSpec, options)], options);
327304
}
328305
override execute(

test/tools/unified-spec-runner/match.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,16 @@ export function resultCheck(
166166
expect(actual[key]).to.have.all.keys(expectedSortKey);
167167
const objFromActual = { [expectedSortKey]: actual[key].get(expectedSortKey) };
168168
resultCheck(objFromActual, value, entities, path, checkExtraKeys);
169-
} else if (key === 'key' && key in actual && actual[key] instanceof Map) {
170-
expect(Object.keys(value)).to.have.lengthOf(1);
171-
expect(actual[key].size).to.equal(1);
172-
resultCheck(Object.fromEntries(actual.key.entries()), value, entities, path, checkExtraKeys);
169+
} else if (key === 'createIndexes') {
170+
for (const index of actual.indexes) {
171+
expect(index).to.have.property('key').that.is.instanceOf(Map);
172+
expect(
173+
index.key.size,
174+
'Test input is JSON and cannot correctly test more than 1 key'
175+
).to.equal(1);
176+
index.key = Object.fromEntries(index.key.entries());
177+
}
178+
resultCheck(actual[key], value, entities, path, checkExtraKeys);
173179
} else {
174180
resultCheck(actual[key], value, entities, path, checkExtraKeys);
175181
}

test/tools/unified-spec-runner/operations.ts

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ operations.set('assertIndexNotExists', async ({ operation, client }) => {
8585
if (error.code === 26 || error.message.includes('ns does not exist')) {
8686
return;
8787
}
88+
// Error will always exist here, this makes the output show what caused an issue with assertIndexNotExists
89+
expect(error).to.not.exist;
8890
}
8991
expect(indexes.map(({ name }) => name)).to.not.include(operation.arguments.indexName);
9092
});

test/unit/operations/indexes.test.ts

+15
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,19 @@ describe('makeIndexSpec()', () => {
125125
expect(realOutput.indexes[0].key).to.deep.equal(desiredMapData);
126126
expect(realOutput.indexes[0].name).to.equal(desiredName);
127127
});
128+
129+
it('should omit options that are not in the permitted list', () => {
130+
const indexOutput = makeIndexOperation(
131+
{ a: 1 },
132+
// @ts-expect-error: Testing bad options get filtered
133+
{ randomOptionThatWillNeverBeAdded: true, storageEngine: { iLoveJavascript: 1 } }
134+
);
135+
expect(indexOutput.indexes).to.have.lengthOf(1);
136+
expect(indexOutput.indexes[0]).to.have.property('key').that.is.instanceOf(Map);
137+
expect(indexOutput.indexes[0]).to.have.property('name', 'a_1');
138+
expect(indexOutput.indexes[0])
139+
.to.have.property('storageEngine')
140+
.that.deep.equals({ iLoveJavascript: 1 });
141+
expect(indexOutput.indexes[0]).to.not.have.property('randomOptionThatWillNeverBeAdded');
142+
});
128143
});

0 commit comments

Comments
 (0)