Skip to content

Commit 15b5f2a

Browse files
authored
fix(query-parser): provide stringify handler for BSONRegExp COMPASS-7008 (#353)
1 parent 04bfb43 commit 15b5f2a

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

packages/query-parser/src/index.spec.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,75 @@ e s`,
521521
const stringified = stringify(res);
522522
assert.equal(stringified, '{name: RegExp("\'")}');
523523
});
524+
525+
it('handles $regex object format (keeps format)', function () {
526+
const res = parseFilter(
527+
'{"name": {"$regex": "pineapple", "$options": "i"}}'
528+
);
529+
const stringified = stringify(res);
530+
assert.equal(
531+
stringified,
532+
"{name: {$regex: 'pineapple',$options: 'i'}}"
533+
);
534+
});
535+
536+
it('handles /regex/ format', function () {
537+
const res = {
538+
name: /pineapple/,
539+
};
540+
const stringified = stringify(res);
541+
assert.equal(stringified, '{name: RegExp("pineapple")}');
542+
});
543+
});
544+
545+
context('when provided a BSONRegExp', function () {
546+
it('stringifies correctly with options', function () {
547+
const res = {
548+
name: new bson.BSONRegExp('pineapple', 'i'),
549+
};
550+
const stringified = stringify(res);
551+
assert.equal(stringified, '{name: RegExp("pineapple", \'i\')}');
552+
});
553+
554+
it('stringifies correctly with quotes', function () {
555+
const res = {
556+
name: new bson.BSONRegExp('"\'', 'i'),
557+
};
558+
const stringified = stringify(res);
559+
assert.equal(stringified, '{name: RegExp("\\"\'", \'i\')}');
560+
});
561+
562+
it('stringifies correctly without options', function () {
563+
const res = {
564+
name: new bson.BSONRegExp('pineapple'),
565+
};
566+
const stringified = stringify(res);
567+
assert.equal(stringified, '{name: RegExp("pineapple")}');
568+
});
569+
570+
it('stringifies into BSONRegExp when js RegExp cannot handle an option', function () {
571+
const res = {
572+
name: new bson.BSONRegExp(
573+
'pineapple',
574+
'x' /* x flag is not valid in js but valid in BSONRegExp*/
575+
),
576+
};
577+
const stringified = stringify(res);
578+
assert.equal(stringified, '{name: BSONRegExp("pineapple", \'x\')}');
579+
});
580+
581+
it('stringifies into BSONRegExp when js RegExp cannot handle the regex', function () {
582+
const res = {
583+
name: new bson.BSONRegExp(
584+
// Perl Compatible Regular Expressions supported feature that isn't in regular
585+
// js RegExp: case-insensitive match.
586+
'(?i)a(?-i)cme',
587+
'i'
588+
),
589+
};
590+
const stringified = stringify(res);
591+
assert.equal(stringified, '{name: BSONRegExp("(?i)a(?-i)cme", \'i\')}');
592+
});
524593
});
525594

526595
context('when provided a Binary', function () {

packages/query-parser/src/stringify.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
import type {
55
Binary,
6+
BSONRegExp,
67
BSONValue,
78
Code,
89
DBRef,
@@ -134,6 +135,18 @@ const BSON_TO_JS_STRING = {
134135

135136
return `RegExp(${JSON.stringify(v.source)}${hasOptions ? `, '${o}'` : ''})`;
136137
},
138+
BSONRegExp: function (v: BSONRegExp) {
139+
const hasOptions = v.options && v.options?.length > 0;
140+
let ctor = 'RegExp';
141+
try {
142+
RegExp(v.pattern, v.options || undefined);
143+
} catch {
144+
ctor = 'BSONRegExp';
145+
}
146+
return `${ctor}(${JSON.stringify(v.pattern)}${
147+
hasOptions ? `, '${v.options}'` : ''
148+
})`;
149+
},
137150
};
138151

139152
/** @public */

0 commit comments

Comments
 (0)