Skip to content

Commit ca9e2dc

Browse files
authored
fix(NODE-3150): allow retrieving PCRE-style RegExp
1 parent 1a57ba8 commit ca9e2dc

File tree

11 files changed

+78
-12
lines changed

11 files changed

+78
-12
lines changed

src/bson.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ export interface BSONSerializeOptions
4848
| 'evalFunctions'
4949
| 'cacheFunctions'
5050
| 'cacheFunctionsCrc32'
51-
| 'bsonRegExp'
5251
| 'allowObjectSmallerThanBufferSize'
5352
| 'index'
5453
> {
@@ -64,6 +63,7 @@ export function pluckBSONSerializeOptions(options: BSONSerializeOptions): BSONSe
6463
promoteLongs,
6564
serializeFunctions,
6665
ignoreUndefined,
66+
bsonRegExp,
6767
raw
6868
} = options;
6969
return {
@@ -73,6 +73,7 @@ export function pluckBSONSerializeOptions(options: BSONSerializeOptions): BSONSe
7373
promoteLongs,
7474
serializeFunctions,
7575
ignoreUndefined,
76+
bsonRegExp,
7677
raw
7778
};
7879
}
@@ -94,6 +95,7 @@ export function resolveBSONOptions(
9495
promoteValues: options?.promoteValues ?? parentOptions?.promoteValues ?? true,
9596
promoteBuffers: options?.promoteBuffers ?? parentOptions?.promoteBuffers ?? false,
9697
ignoreUndefined: options?.ignoreUndefined ?? parentOptions?.ignoreUndefined ?? false,
98+
bsonRegExp: options?.bsonRegExp ?? parentOptions?.bsonRegExp ?? false,
9799
serializeFunctions: options?.serializeFunctions ?? parentOptions?.serializeFunctions ?? false,
98100
fieldsAsRaw: options?.fieldsAsRaw ?? parentOptions?.fieldsAsRaw ?? {}
99101
};

src/cmap/auth/mongodb_aws.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ const AWS_EC2_PATH = '/latest/meta-data/iam/security-credentials';
1818
const bsonOptions: BSONSerializeOptions = {
1919
promoteLongs: true,
2020
promoteValues: true,
21-
promoteBuffers: false
21+
promoteBuffers: false,
22+
bsonRegExp: false
2223
};
2324

2425
interface AWSSaslContinuePayload {

src/cmap/commands.ts

+26-8
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ export class Response {
491491
promoteLongs: boolean;
492492
promoteValues: boolean;
493493
promoteBuffers: boolean;
494+
bsonRegExp?: boolean;
494495
index?: number;
495496

496497
constructor(
@@ -502,7 +503,12 @@ export class Response {
502503
this.parsed = false;
503504
this.raw = message;
504505
this.data = msgBody;
505-
this.opts = opts ?? { promoteLongs: true, promoteValues: true, promoteBuffers: false };
506+
this.opts = opts ?? {
507+
promoteLongs: true,
508+
promoteValues: true,
509+
promoteBuffers: false,
510+
bsonRegExp: false
511+
};
506512

507513
// Read the message header
508514
this.length = msgHeader.length;
@@ -530,6 +536,7 @@ export class Response {
530536
typeof this.opts.promoteValues === 'boolean' ? this.opts.promoteValues : true;
531537
this.promoteBuffers =
532538
typeof this.opts.promoteBuffers === 'boolean' ? this.opts.promoteBuffers : false;
539+
this.bsonRegExp = typeof this.opts.bsonRegExp === 'boolean' ? this.opts.bsonRegExp : false;
533540
}
534541

535542
isParsed(): boolean {
@@ -547,13 +554,15 @@ export class Response {
547554
const promoteLongs = options.promoteLongs ?? this.opts.promoteLongs;
548555
const promoteValues = options.promoteValues ?? this.opts.promoteValues;
549556
const promoteBuffers = options.promoteBuffers ?? this.opts.promoteBuffers;
557+
const bsonRegExp = options.bsonRegExp ?? this.opts.bsonRegExp;
550558
let bsonSize;
551559

552560
// Set up the options
553561
const _options: BSONSerializeOptions = {
554-
promoteLongs: promoteLongs,
555-
promoteValues: promoteValues,
556-
promoteBuffers: promoteBuffers
562+
promoteLongs,
563+
promoteValues,
564+
promoteBuffers,
565+
bsonRegExp
557566
};
558567

559568
// Position within OP_REPLY at which documents start
@@ -765,6 +774,7 @@ export class BinMsg {
765774
promoteLongs: boolean;
766775
promoteValues: boolean;
767776
promoteBuffers: boolean;
777+
bsonRegExp: boolean;
768778
documents: (Document | Buffer)[];
769779
index?: number;
770780

@@ -777,7 +787,12 @@ export class BinMsg {
777787
this.parsed = false;
778788
this.raw = message;
779789
this.data = msgBody;
780-
this.opts = opts ?? { promoteLongs: true, promoteValues: true, promoteBuffers: false };
790+
this.opts = opts ?? {
791+
promoteLongs: true,
792+
promoteValues: true,
793+
promoteBuffers: false,
794+
bsonRegExp: false
795+
};
781796

782797
// Read the message header
783798
this.length = msgHeader.length;
@@ -796,6 +811,7 @@ export class BinMsg {
796811
typeof this.opts.promoteValues === 'boolean' ? this.opts.promoteValues : true;
797812
this.promoteBuffers =
798813
typeof this.opts.promoteBuffers === 'boolean' ? this.opts.promoteBuffers : false;
814+
this.bsonRegExp = typeof this.opts.bsonRegExp === 'boolean' ? this.opts.bsonRegExp : false;
799815

800816
this.documents = [];
801817
}
@@ -816,12 +832,14 @@ export class BinMsg {
816832
const promoteLongs = options.promoteLongs ?? this.opts.promoteLongs;
817833
const promoteValues = options.promoteValues ?? this.opts.promoteValues;
818834
const promoteBuffers = options.promoteBuffers ?? this.opts.promoteBuffers;
835+
const bsonRegExp = options.bsonRegExp ?? this.opts.bsonRegExp;
819836

820837
// Set up the options
821838
const _options: BSONSerializeOptions = {
822-
promoteLongs: promoteLongs,
823-
promoteValues: promoteValues,
824-
promoteBuffers: promoteBuffers
839+
promoteLongs,
840+
promoteValues,
841+
promoteBuffers,
842+
bsonRegExp
825843
};
826844

827845
while (this.index < this.data.length) {

src/cmap/connection.ts

+1
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ function write(
792792
promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
793793
promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
794794
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
795+
bsonRegExp: typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false,
795796
raw: typeof options.raw === 'boolean' ? options.raw : false,
796797
started: 0
797798
};

src/cmap/wire_protocol/shared.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ export function applyCommonQueryOptions(
4242
raw: typeof options.raw === 'boolean' ? options.raw : false,
4343
promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
4444
promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
45-
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false
45+
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
46+
bsonRegExp: typeof options.bsonRegExp === 'boolean' ? options.bsonRegExp : false
4647
});
4748

4849
if (options.session) {

src/connection_string.ts

+3
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,9 @@ export const OPTIONS = {
588588
autoEncryption: {
589589
type: 'record'
590590
},
591+
bsonRegExp: {
592+
type: 'boolean'
593+
},
591594
serverApi: {
592595
target: 'serverApi',
593596
transform({ values: [version] }): ServerApi {

src/db.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ const DB_OPTIONS_ALLOW_LIST = [
6161
'raw',
6262
'authSource',
6363
'ignoreUndefined',
64-
'promoteLongs',
6564
'readConcern',
6665
'retryMiliSeconds',
6766
'numberOfRetries',
6867
'loggerLevel',
6968
'logger',
7069
'promoteBuffers',
7170
'promoteLongs',
71+
'bsonRegExp',
7272
'promoteValues',
7373
'compression',
7474
'retryWrites'

src/operations/create_collection.ts

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const ILLEGAL_COMMAND_FIELDS = new Set([
2525
'promoteLongs',
2626
'promoteValues',
2727
'promoteBuffers',
28+
'bsonRegExp',
2829
'serializeFunctions',
2930
'ignoreUndefined'
3031
]);

src/operations/map_reduce.ts

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const exclusionList = [
3030
'promoteLongs',
3131
'promoteValues',
3232
'promoteBuffers',
33+
'bsonRegExp',
3334
'serializeFunctions',
3435
'ignoreUndefined',
3536
'scope' // this option is reformatted thus exclude the original

test/types/bson.test-d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ expectType<boolean | undefined>(options.ignoreUndefined);
99
expectType<boolean | undefined>(options.promoteLongs);
1010
expectType<boolean | undefined>(options.promoteBuffers);
1111
expectType<boolean | undefined>(options.promoteValues);
12+
expectType<boolean | undefined>(options.bsonRegExp);
1213
expectType<Document | undefined>(options.fieldsAsRaw);
1314

1415
type PermittedBSONOptionKeys =
@@ -18,6 +19,7 @@ type PermittedBSONOptionKeys =
1819
| 'promoteLongs'
1920
| 'promoteBuffers'
2021
| 'promoteValues'
22+
| 'bsonRegExp'
2123
| 'fieldsAsRaw'
2224
| 'raw';
2325

test/unit/bson_regex.test.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
3+
const { expect } = require('chai');
4+
const { BSONRegExp } = require('../../src/index');
5+
6+
describe('BSONRegExp', () => {
7+
describe('bsonRegExp option', () => {
8+
// define client and option for tests to use
9+
let client;
10+
const option = { bsonRegExp: true };
11+
for (const passOptionTo of ['client', 'db', 'collection', 'operation']) {
12+
it(`should respond with BSONRegExp class with option passed to ${passOptionTo}`, async function () {
13+
try {
14+
client = this.configuration.newClient(passOptionTo === 'client' ? option : undefined);
15+
await client.connect();
16+
17+
const db = client.db('bson_regex_db', passOptionTo === 'db' ? option : undefined);
18+
const collection = db.collection(
19+
'bson_regex_coll',
20+
passOptionTo === 'collection' ? option : undefined
21+
);
22+
23+
await collection.insertOne({ regex: new BSONRegExp('abc', 'imx') });
24+
const res = await collection.findOne(
25+
{ regex: new BSONRegExp('abc', 'imx') },
26+
passOptionTo === 'operation' ? option : undefined
27+
);
28+
29+
expect(res).has.property('regex').that.is.instanceOf(BSONRegExp);
30+
} finally {
31+
await client.close();
32+
}
33+
});
34+
}
35+
});
36+
});

0 commit comments

Comments
 (0)