opusdev/vector-similarity-api
1
1import { BSONValue } from './bson_value';2import { BSONError } from './error';3import type { EJSONOptions } from './extended_json';4import { type InspectFn, defaultInspect, getStylizeFunction } from './parser/utils';5 6function alphabetize(str: string): string {7 return str.split('').sort().join('');8}9 10/** @public */11export interface BSONRegExpExtendedLegacy {12 $regex: string | BSONRegExp;13 $options: string;14}15 16/** @public */17export interface BSONRegExpExtended {18 $regularExpression: {19 pattern: string;20 options: string;21 };22}23 24/**25 * A class representation of the BSON RegExp type.26 * @public27 * @category BSONType28 */29export class BSONRegExp extends BSONValue {30 get _bsontype(): 'BSONRegExp' {31 return 'BSONRegExp';32 }33 34 pattern!: string;35 options!: string;36 /**37 * @param pattern - The regular expression pattern to match38 * @param options - The regular expression options39 */40 constructor(pattern: string, options?: string) {41 super();42 this.pattern = pattern;43 this.options = alphabetize(options ?? '');44 45 if (this.pattern.indexOf('\x00') !== -1) {46 throw new BSONError(47 `BSON Regex patterns cannot contain null bytes, found: ${JSON.stringify(this.pattern)}`48 );49 }50 if (this.options.indexOf('\x00') !== -1) {51 throw new BSONError(52 `BSON Regex options cannot contain null bytes, found: ${JSON.stringify(this.options)}`53 );54 }55 56 // Validate options57 for (let i = 0; i < this.options.length; i++) {58 if (59 !(60 this.options[i] === 'i' ||61 this.options[i] === 'm' ||62 this.options[i] === 'x' ||63 this.options[i] === 'l' ||64 this.options[i] === 's' ||65 this.options[i] === 'u'66 )67 ) {68 throw new BSONError(`The regular expression option [${this.options[i]}] is not supported`);69 }70 }71 }72 73 static parseOptions(options?: string): string {74 return options ? options.split('').sort().join('') : '';75 }76 77 /** @internal */78 toExtendedJSON(options?: EJSONOptions): BSONRegExpExtendedLegacy | BSONRegExpExtended {79 options = options || {};80 if (options.legacy) {81 return { $regex: this.pattern, $options: this.options };82 }83 return { $regularExpression: { pattern: this.pattern, options: this.options } };84 }85 86 /** @internal */87 static fromExtendedJSON(doc: BSONRegExpExtendedLegacy | BSONRegExpExtended): BSONRegExp {88 if ('$regex' in doc) {89 if (typeof doc.$regex !== 'string') {90 // This is for $regex query operators that have extended json values.91 if (doc.$regex._bsontype === 'BSONRegExp') {92 return doc as unknown as BSONRegExp;93 }94 } else {95 return new BSONRegExp(doc.$regex, BSONRegExp.parseOptions(doc.$options));96 }97 }98 if ('$regularExpression' in doc) {99 return new BSONRegExp(100 doc.$regularExpression.pattern,101 BSONRegExp.parseOptions(doc.$regularExpression.options)102 );103 }104 throw new BSONError(`Unexpected BSONRegExp EJSON object form: ${JSON.stringify(doc)}`);105 }106 107 inspect(depth?: number, options?: unknown, inspect?: InspectFn): string {108 const stylize = getStylizeFunction(options) ?? (v => v);109 inspect ??= defaultInspect;110 const pattern = stylize(inspect(this.pattern), 'regexp');111 const flags = stylize(inspect(this.options), 'regexp');112 return `new BSONRegExp(${pattern}, ${flags})`;113 }114}115 