Skip to content

Commit e0996a7

Browse files
committed
fix: simplify BSON type detection, add regex and function
1 parent eb223d9 commit e0996a7

File tree

2 files changed

+67
-13
lines changed

2 files changed

+67
-13
lines changed

src/mongo_types.ts

+5-8
Original file line numberDiff line numberDiff line change
@@ -483,15 +483,12 @@ export type NestedPaths<Type> = Type extends
483483
| string
484484
| number
485485
| boolean
486-
| BSONRegExp
487-
| Binary
488486
| Date
489-
| Decimal128
490-
| Double
491-
| Int32
492-
| Long
493-
| ObjectId
494-
| Timestamp
487+
| RegExp
488+
| Buffer
489+
| Uint8Array
490+
| ((...args: any[]) => any)
491+
| { _bsontype: string }
495492
? []
496493
: Type extends ReadonlyArray<infer ArrayType>
497494
? [number, ...NestedPaths<ArrayType>]

test/types/community/collection/filterQuery.test-d.ts

+62-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
import { BSONRegExp, Decimal128, Long, ObjectId } from 'bson';
1+
import {
2+
Binary,
3+
BSONRegExp,
4+
BSONSymbol,
5+
Code,
6+
DBRef,
7+
Decimal128,
8+
Long,
9+
MaxKey,
10+
MinKey,
11+
ObjectId
12+
} from 'bson';
213
import { expectAssignable, expectError, expectNotType, expectType } from 'tsd';
314

415
import { Collection, Filter, MongoClient, WithId } from '../../../../src';
@@ -47,6 +58,17 @@ interface PetModel {
4758
};
4859
};
4960
};
61+
62+
binary: Binary;
63+
code: Code;
64+
minKey: MinKey;
65+
maxKey: MaxKey;
66+
dBRef: DBRef;
67+
bSONSymbol: BSONSymbol;
68+
69+
regex: RegExp;
70+
71+
fn: (...args: any[]) => any;
5072
}
5173

5274
const john = {
@@ -64,15 +86,28 @@ const spot = {
6486
createdAt: new Date(),
6587
numOfPats: Long.fromBigInt(100000000n),
6688
treats: ['kibble', 'bone'],
67-
playTimePercent: new Decimal128('0.999999')
89+
playTimePercent: new Decimal128('0.999999'),
90+
91+
binary: new Binary('', 2),
92+
code: new Code(() => true),
93+
minKey: new MinKey(),
94+
maxKey: new MaxKey(),
95+
dBRef: new DBRef('collection', new ObjectId()),
96+
bSONSymbol: new BSONSymbol('hi'),
97+
98+
regex: /a/,
99+
100+
fn() {
101+
return 'hi';
102+
}
68103
};
69104

70105
expectAssignable<PetModel>(spot);
71106

72107
const collectionT = db.collection<PetModel>('test.filterQuery');
73108

74109
// Assert that collection.find uses the Filter helper like so:
75-
const filter: Filter<PetModel> = {};
110+
const filter: Filter<PetModel> = {} as Filter<PetModel>;
76111
collectionT.find(filter);
77112
collectionT.find(spot); // a whole model definition is also a valid filter
78113
// Now tests below can directly test the Filter helper, and are implicitly checking collection.find
@@ -96,6 +131,10 @@ expectNotType<Filter<PetModel>>({ name: 23 });
96131
expectNotType<Filter<PetModel>>({ name: { suffix: 'Jr' } });
97132
expectNotType<Filter<PetModel>>({ name: ['Spot'] });
98133

134+
// it should not accept wrong types for function fields
135+
expectNotType<Filter<PetModel>>({ fn: 3 });
136+
expectAssignable<WithId<PetModel>[]>(await collectionT.find({ fn: () => true }).toArray());
137+
99138
/// it should query __number__ fields
100139
await collectionT.find({ age: 12 }).toArray();
101140
/// it should not accept wrong types for number fields
@@ -115,6 +154,26 @@ expectNotType<Filter<PetModel>>({ bestFriend: 'Andersons' });
115154
expectNotType<Filter<PetModel>>({ bestFriend: [spot] });
116155
expectNotType<Filter<PetModel>>({ bestFriend: [{ name: 'Andersons' }] });
117156

157+
// it should permit all our BSON types as query values
158+
expectAssignable<Filter<PetModel>>({ binary: new Binary('', 2) });
159+
expectAssignable<Filter<PetModel>>({ code: new Code(() => true) });
160+
expectAssignable<Filter<PetModel>>({ minKey: new MinKey() });
161+
expectAssignable<Filter<PetModel>>({ maxKey: new MaxKey() });
162+
expectAssignable<Filter<PetModel>>({ dBRef: new DBRef('collection', new ObjectId()) });
163+
expectAssignable<Filter<PetModel>>({ bSONSymbol: new BSONSymbol('hi') });
164+
165+
// None of the bson types should be broken up into their nested keys
166+
expectNotType<Filter<PetModel>>({ 'binary.sub_type': 2 });
167+
expectNotType<Filter<PetModel>>({ 'code.code': 'string' });
168+
expectNotType<Filter<PetModel>>({ 'minKey._bsontype': 'MinKey' });
169+
expectNotType<Filter<PetModel>>({ 'maxKey._bsontype': 'MaxKey' });
170+
expectNotType<Filter<PetModel>>({ 'dBRef.collection': 'collection' });
171+
expectNotType<Filter<PetModel>>({ 'bSONSymbol.value': 'hi' });
172+
expectNotType<Filter<PetModel>>({ 'numOfPats.__isLong__': true });
173+
expectNotType<Filter<PetModel>>({ 'playTimePercent.bytes.BYTES_PER_ELEMENT': 1 });
174+
expectNotType<Filter<PetModel>>({ 'binary.sub_type': 'blah' });
175+
expectNotType<Filter<PetModel>>({ 'regex.dotAll': true });
176+
118177
/// it should query __nested document__ fields using dot-notation
119178
collectionT.find({ 'meta.updatedAt': new Date() });
120179
collectionT.find({ 'meta.deep.nested.level': 123 });
@@ -144,8 +203,6 @@ expectNotType<Filter<PetModel>>({ 'friends.0.name': 123 });
144203
expectNotType<Filter<PetModel>>({ 'playmates.0.name': 123 });
145204
expectNotType<Filter<PetModel>>({ 'laps.foo': 'string' });
146205
expectNotType<Filter<PetModel>>({ 'treats.0': 123 });
147-
expectNotType<Filter<PetModel>>({ 'numOfPats.__isLong__': true });
148-
expectNotType<Filter<PetModel>>({ 'playTimePercent.bytes.BYTES_PER_ELEMENT': 1 });
149206

150207
// Nested arrays aren't checked
151208
expectNotType<Filter<PetModel>>({ 'meta.deep.nestedArray.0': 'not a number' });

0 commit comments

Comments
 (0)