opusdev/vector-similarity-api
1
1'use strict';2 3const TypedArrayPrototypeGetSymbolToStringTag = (() => {4 const g = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), Symbol.toStringTag).get;5 return (value) => g.call(value);6})();7function isUint8Array(value) {8 return TypedArrayPrototypeGetSymbolToStringTag(value) === 'Uint8Array';9}10function isAnyArrayBuffer(value) {11 return (typeof value === 'object' &&12 value != null &&13 Symbol.toStringTag in value &&14 (value[Symbol.toStringTag] === 'ArrayBuffer' ||15 value[Symbol.toStringTag] === 'SharedArrayBuffer'));16}17function isRegExp(regexp) {18 return regexp instanceof RegExp || Object.prototype.toString.call(regexp) === '[object RegExp]';19}20function isMap(value) {21 return (typeof value === 'object' &&22 value != null &&23 Symbol.toStringTag in value &&24 value[Symbol.toStringTag] === 'Map');25}26function isDate(date) {27 return date instanceof Date || Object.prototype.toString.call(date) === '[object Date]';28}29function defaultInspect(x, _options) {30 return JSON.stringify(x, (k, v) => {31 if (typeof v === 'bigint') {32 return { $numberLong: `${v}` };33 }34 else if (isMap(v)) {35 return Object.fromEntries(v);36 }37 return v;38 });39}40function getStylizeFunction(options) {41 const stylizeExists = options != null &&42 typeof options === 'object' &&43 'stylize' in options &&44 typeof options.stylize === 'function';45 if (stylizeExists) {46 return options.stylize;47 }48}49 50const BSON_MAJOR_VERSION = 6;51const BSON_VERSION_SYMBOL = Symbol.for('@@mdb.bson.version');52const BSON_INT32_MAX = 0x7fffffff;53const BSON_INT32_MIN = -2147483648;54const BSON_INT64_MAX = Math.pow(2, 63) - 1;55const BSON_INT64_MIN = -Math.pow(2, 63);56const JS_INT_MAX = Math.pow(2, 53);57const JS_INT_MIN = -Math.pow(2, 53);58const BSON_DATA_NUMBER = 1;59const BSON_DATA_STRING = 2;60const BSON_DATA_OBJECT = 3;61const BSON_DATA_ARRAY = 4;62const BSON_DATA_BINARY = 5;63const BSON_DATA_UNDEFINED = 6;64const BSON_DATA_OID = 7;65const BSON_DATA_BOOLEAN = 8;66const BSON_DATA_DATE = 9;67const BSON_DATA_NULL = 10;68const BSON_DATA_REGEXP = 11;69const BSON_DATA_DBPOINTER = 12;70const BSON_DATA_CODE = 13;71const BSON_DATA_SYMBOL = 14;72const BSON_DATA_CODE_W_SCOPE = 15;73const BSON_DATA_INT = 16;74const BSON_DATA_TIMESTAMP = 17;75const BSON_DATA_LONG = 18;76const BSON_DATA_DECIMAL128 = 19;77const BSON_DATA_MIN_KEY = 0xff;78const BSON_DATA_MAX_KEY = 0x7f;79const BSON_BINARY_SUBTYPE_DEFAULT = 0;80const BSON_BINARY_SUBTYPE_UUID_NEW = 4;81const BSONType = Object.freeze({82 double: 1,83 string: 2,84 object: 3,85 array: 4,86 binData: 5,87 undefined: 6,88 objectId: 7,89 bool: 8,90 date: 9,91 null: 10,92 regex: 11,93 dbPointer: 12,94 javascript: 13,95 symbol: 14,96 javascriptWithScope: 15,97 int: 16,98 timestamp: 17,99 long: 18,100 decimal: 19,101 minKey: -1,102 maxKey: 127103});104 105class BSONError extends Error {106 get bsonError() {107 return true;108 }109 get name() {110 return 'BSONError';111 }112 constructor(message, options) {113 super(message, options);114 }115 static isBSONError(value) {116 return (value != null &&117 typeof value === 'object' &&118 'bsonError' in value &&119 value.bsonError === true &&120 'name' in value &&121 'message' in value &&122 'stack' in value);123 }124}125class BSONVersionError extends BSONError {126 get name() {127 return 'BSONVersionError';128 }129 constructor() {130 super(`Unsupported BSON version, bson types must be from bson ${BSON_MAJOR_VERSION}.x.x`);131 }132}133class BSONRuntimeError extends BSONError {134 get name() {135 return 'BSONRuntimeError';136 }137 constructor(message) {138 super(message);139 }140}141class BSONOffsetError extends BSONError {142 get name() {143 return 'BSONOffsetError';144 }145 constructor(message, offset, options) {146 super(`${message}. offset: ${offset}`, options);147 this.offset = offset;148 }149}150 151let TextDecoderFatal;152let TextDecoderNonFatal;153function parseUtf8(buffer, start, end, fatal) {154 if (fatal) {155 TextDecoderFatal ??= new TextDecoder('utf8', { fatal: true });156 try {157 return TextDecoderFatal.decode(buffer.subarray(start, end));158 }159 catch (cause) {160 throw new BSONError('Invalid UTF-8 string in BSON document', { cause });161 }162 }163 TextDecoderNonFatal ??= new TextDecoder('utf8', { fatal: false });164 return TextDecoderNonFatal.decode(buffer.subarray(start, end));165}166 167function tryReadBasicLatin(uint8array, start, end) {168 if (uint8array.length === 0) {169 return '';170 }171 const stringByteLength = end - start;172 if (stringByteLength === 0) {173 return '';174 }175 if (stringByteLength > 20) {176 return null;177 }178 if (stringByteLength === 1 && uint8array[start] < 128) {179 return String.fromCharCode(uint8array[start]);180 }181 if (stringByteLength === 2 && uint8array[start] < 128 && uint8array[start + 1] < 128) {182 return String.fromCharCode(uint8array[start]) + String.fromCharCode(uint8array[start + 1]);183 }184 if (stringByteLength === 3 &&185 uint8array[start] < 128 &&186 uint8array[start + 1] < 128 &&187 uint8array[start + 2] < 128) {188 return (String.fromCharCode(uint8array[start]) +189 String.fromCharCode(uint8array[start + 1]) +190 String.fromCharCode(uint8array[start + 2]));191 }192 const latinBytes = [];193 for (let i = start; i < end; i++) {194 const byte = uint8array[i];195 if (byte > 127) {196 return null;197 }198 latinBytes.push(byte);199 }200 return String.fromCharCode(...latinBytes);201}202function tryWriteBasicLatin(destination, source, offset) {203 if (source.length === 0)204 return 0;205 if (source.length > 25)206 return null;207 if (destination.length - offset < source.length)208 return null;209 for (let charOffset = 0, destinationOffset = offset; charOffset < source.length; charOffset++, destinationOffset++) {210 const char = source.charCodeAt(charOffset);211 if (char > 127)212 return null;213 destination[destinationOffset] = char;214 }215 return source.length;216}217 218function nodejsMathRandomBytes(byteLength) {219 return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));220}221const nodejsRandomBytes = (() => {222 try {223 return require('crypto').randomBytes;224 }225 catch {226 return nodejsMathRandomBytes;227 }228})();229const nodeJsByteUtils = {230 toLocalBufferType(potentialBuffer) {231 if (Buffer.isBuffer(potentialBuffer)) {232 return potentialBuffer;233 }234 if (ArrayBuffer.isView(potentialBuffer)) {235 return Buffer.from(potentialBuffer.buffer, potentialBuffer.byteOffset, potentialBuffer.byteLength);236 }237 const stringTag = potentialBuffer?.[Symbol.toStringTag] ?? Object.prototype.toString.call(potentialBuffer);238 if (stringTag === 'ArrayBuffer' ||239 stringTag === 'SharedArrayBuffer' ||240 stringTag === '[object ArrayBuffer]' ||241 stringTag === '[object SharedArrayBuffer]') {242 return Buffer.from(potentialBuffer);243 }244 throw new BSONError(`Cannot create Buffer from the passed potentialBuffer.`);245 },246 allocate(size) {247 return Buffer.alloc(size);248 },249 allocateUnsafe(size) {250 return Buffer.allocUnsafe(size);251 },252 equals(a, b) {253 return nodeJsByteUtils.toLocalBufferType(a).equals(b);254 },255 fromNumberArray(array) {256 return Buffer.from(array);257 },258 fromBase64(base64) {259 return Buffer.from(base64, 'base64');260 },261 toBase64(buffer) {262 return nodeJsByteUtils.toLocalBufferType(buffer).toString('base64');263 },264 fromISO88591(codePoints) {265 return Buffer.from(codePoints, 'binary');266 },267 toISO88591(buffer) {268 return nodeJsByteUtils.toLocalBufferType(buffer).toString('binary');269 },270 fromHex(hex) {271 return Buffer.from(hex, 'hex');272 },273 toHex(buffer) {274 return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');275 },276 toUTF8(buffer, start, end, fatal) {277 const basicLatin = end - start <= 20 ? tryReadBasicLatin(buffer, start, end) : null;278 if (basicLatin != null) {279 return basicLatin;280 }281 const string = nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);282 if (fatal) {283 for (let i = 0; i < string.length; i++) {284 if (string.charCodeAt(i) === 0xfffd) {285 parseUtf8(buffer, start, end, true);286 break;287 }288 }289 }290 return string;291 },292 utf8ByteLength(input) {293 return Buffer.byteLength(input, 'utf8');294 },295 encodeUTF8Into(buffer, source, byteOffset) {296 const latinBytesWritten = tryWriteBasicLatin(buffer, source, byteOffset);297 if (latinBytesWritten != null) {298 return latinBytesWritten;299 }300 return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');301 },302 randomBytes: nodejsRandomBytes,303 swap32(buffer) {304 return nodeJsByteUtils.toLocalBufferType(buffer).swap32();305 }306};307 308function isReactNative() {309 const { navigator } = globalThis;310 return typeof navigator === 'object' && navigator.product === 'ReactNative';311}312function webMathRandomBytes(byteLength) {313 if (byteLength < 0) {314 throw new RangeError(`The argument 'byteLength' is invalid. Received ${byteLength}`);315 }316 return webByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));317}318const webRandomBytes = (() => {319 const { crypto } = globalThis;320 if (crypto != null && typeof crypto.getRandomValues === 'function') {321 return (byteLength) => {322 return crypto.getRandomValues(webByteUtils.allocate(byteLength));323 };324 }325 else {326 if (isReactNative()) {327 const { console } = globalThis;328 console?.warn?.('BSON: For React Native please polyfill crypto.getRandomValues, e.g. using: https://www.npmjs.com/package/react-native-get-random-values.');329 }330 return webMathRandomBytes;331 }332})();333const HEX_DIGIT = /(\d|[a-f])/i;334const webByteUtils = {335 toLocalBufferType(potentialUint8array) {336 const stringTag = potentialUint8array?.[Symbol.toStringTag] ??337 Object.prototype.toString.call(potentialUint8array);338 if (stringTag === 'Uint8Array') {339 return potentialUint8array;340 }341 if (ArrayBuffer.isView(potentialUint8array)) {342 return new Uint8Array(potentialUint8array.buffer.slice(potentialUint8array.byteOffset, potentialUint8array.byteOffset + potentialUint8array.byteLength));343 }344 if (stringTag === 'ArrayBuffer' ||345 stringTag === 'SharedArrayBuffer' ||346 stringTag === '[object ArrayBuffer]' ||347 stringTag === '[object SharedArrayBuffer]') {348 return new Uint8Array(potentialUint8array);349 }350 throw new BSONError(`Cannot make a Uint8Array from passed potentialBuffer.`);351 },352 allocate(size) {353 if (typeof size !== 'number') {354 throw new TypeError(`The "size" argument must be of type number. Received ${String(size)}`);355 }356 return new Uint8Array(size);357 },358 allocateUnsafe(size) {359 return webByteUtils.allocate(size);360 },361 equals(a, b) {362 if (a.byteLength !== b.byteLength) {363 return false;364 }365 for (let i = 0; i < a.byteLength; i++) {366 if (a[i] !== b[i]) {367 return false;368 }369 }370 return true;371 },372 fromNumberArray(array) {373 return Uint8Array.from(array);374 },375 fromBase64(base64) {376 return Uint8Array.from(atob(base64), c => c.charCodeAt(0));377 },378 toBase64(uint8array) {379 return btoa(webByteUtils.toISO88591(uint8array));380 },381 fromISO88591(codePoints) {382 return Uint8Array.from(codePoints, c => c.charCodeAt(0) & 0xff);383 },384 toISO88591(uint8array) {385 return Array.from(Uint16Array.from(uint8array), b => String.fromCharCode(b)).join('');386 },387 fromHex(hex) {388 const evenLengthHex = hex.length % 2 === 0 ? hex : hex.slice(0, hex.length - 1);389 const buffer = [];390 for (let i = 0; i < evenLengthHex.length; i += 2) {391 const firstDigit = evenLengthHex[i];392 const secondDigit = evenLengthHex[i + 1];393 if (!HEX_DIGIT.test(firstDigit)) {394 break;395 }396 if (!HEX_DIGIT.test(secondDigit)) {397 break;398 }399 const hexDigit = Number.parseInt(`${firstDigit}${secondDigit}`, 16);400 buffer.push(hexDigit);401 }402 return Uint8Array.from(buffer);403 },404 toHex(uint8array) {405 return Array.from(uint8array, byte => byte.toString(16).padStart(2, '0')).join('');406 },407 toUTF8(uint8array, start, end, fatal) {408 const basicLatin = end - start <= 20 ? tryReadBasicLatin(uint8array, start, end) : null;409 if (basicLatin != null) {410 return basicLatin;411 }412 return parseUtf8(uint8array, start, end, fatal);413 },414 utf8ByteLength(input) {415 return new TextEncoder().encode(input).byteLength;416 },417 encodeUTF8Into(uint8array, source, byteOffset) {418 const bytes = new TextEncoder().encode(source);419 uint8array.set(bytes, byteOffset);420 return bytes.byteLength;421 },422 randomBytes: webRandomBytes,423 swap32(buffer) {424 if (buffer.length % 4 !== 0) {425 throw new RangeError('Buffer size must be a multiple of 32-bits');426 }427 for (let i = 0; i < buffer.length; i += 4) {428 const byte0 = buffer[i];429 const byte1 = buffer[i + 1];430 const byte2 = buffer[i + 2];431 const byte3 = buffer[i + 3];432 buffer[i] = byte3;433 buffer[i + 1] = byte2;434 buffer[i + 2] = byte1;435 buffer[i + 3] = byte0;436 }437 return buffer;438 }439};440 441const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;442const ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;443 444class BSONValue {445 get [BSON_VERSION_SYMBOL]() {446 return BSON_MAJOR_VERSION;447 }448 [Symbol.for('nodejs.util.inspect.custom')](depth, options, inspect) {449 return this.inspect(depth, options, inspect);450 }451}452 453const FLOAT = new Float64Array(1);454const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);455FLOAT[0] = -1;456const isBigEndian = FLOAT_BYTES[7] === 0;457const NumberUtils = {458 isBigEndian,459 getNonnegativeInt32LE(source, offset) {460 if (source[offset + 3] > 127) {461 throw new RangeError(`Size cannot be negative at offset: ${offset}`);462 }463 return (source[offset] |464 (source[offset + 1] << 8) |465 (source[offset + 2] << 16) |466 (source[offset + 3] << 24));467 },468 getInt32LE(source, offset) {469 return (source[offset] |470 (source[offset + 1] << 8) |471 (source[offset + 2] << 16) |472 (source[offset + 3] << 24));473 },474 getUint32LE(source, offset) {475 return (source[offset] +476 source[offset + 1] * 256 +477 source[offset + 2] * 65536 +478 source[offset + 3] * 16777216);479 },480 getUint32BE(source, offset) {481 return (source[offset + 3] +482 source[offset + 2] * 256 +483 source[offset + 1] * 65536 +484 source[offset] * 16777216);485 },486 getBigInt64LE(source, offset) {487 const hi = BigInt(source[offset + 4] +488 source[offset + 5] * 256 +489 source[offset + 6] * 65536 +490 (source[offset + 7] << 24));491 const lo = BigInt(source[offset] +492 source[offset + 1] * 256 +493 source[offset + 2] * 65536 +494 source[offset + 3] * 16777216);495 return (hi << BigInt(32)) + lo;496 },497 getFloat64LE: isBigEndian498 ? (source, offset) => {499 FLOAT_BYTES[7] = source[offset];500 FLOAT_BYTES[6] = source[offset + 1];501 FLOAT_BYTES[5] = source[offset + 2];502 FLOAT_BYTES[4] = source[offset + 3];503 FLOAT_BYTES[3] = source[offset + 4];504 FLOAT_BYTES[2] = source[offset + 5];505 FLOAT_BYTES[1] = source[offset + 6];506 FLOAT_BYTES[0] = source[offset + 7];507 return FLOAT[0];508 }509 : (source, offset) => {510 FLOAT_BYTES[0] = source[offset];511 FLOAT_BYTES[1] = source[offset + 1];512 FLOAT_BYTES[2] = source[offset + 2];513 FLOAT_BYTES[3] = source[offset + 3];514 FLOAT_BYTES[4] = source[offset + 4];515 FLOAT_BYTES[5] = source[offset + 5];516 FLOAT_BYTES[6] = source[offset + 6];517 FLOAT_BYTES[7] = source[offset + 7];518 return FLOAT[0];519 },520 setInt32BE(destination, offset, value) {521 destination[offset + 3] = value;522 value >>>= 8;523 destination[offset + 2] = value;524 value >>>= 8;525 destination[offset + 1] = value;526 value >>>= 8;527 destination[offset] = value;528 return 4;529 },530 setInt32LE(destination, offset, value) {531 destination[offset] = value;532 value >>>= 8;533 destination[offset + 1] = value;534 value >>>= 8;535 destination[offset + 2] = value;536 value >>>= 8;537 destination[offset + 3] = value;538 return 4;539 },540 setBigInt64LE(destination, offset, value) {541 const mask32bits = BigInt(0xffff_ffff);542 let lo = Number(value & mask32bits);543 destination[offset] = lo;544 lo >>= 8;545 destination[offset + 1] = lo;546 lo >>= 8;547 destination[offset + 2] = lo;548 lo >>= 8;549 destination[offset + 3] = lo;550 let hi = Number((value >> BigInt(32)) & mask32bits);551 destination[offset + 4] = hi;552 hi >>= 8;553 destination[offset + 5] = hi;554 hi >>= 8;555 destination[offset + 6] = hi;556 hi >>= 8;557 destination[offset + 7] = hi;558 return 8;559 },560 setFloat64LE: isBigEndian561 ? (destination, offset, value) => {562 FLOAT[0] = value;563 destination[offset] = FLOAT_BYTES[7];564 destination[offset + 1] = FLOAT_BYTES[6];565 destination[offset + 2] = FLOAT_BYTES[5];566 destination[offset + 3] = FLOAT_BYTES[4];567 destination[offset + 4] = FLOAT_BYTES[3];568 destination[offset + 5] = FLOAT_BYTES[2];569 destination[offset + 6] = FLOAT_BYTES[1];570 destination[offset + 7] = FLOAT_BYTES[0];571 return 8;572 }573 : (destination, offset, value) => {574 FLOAT[0] = value;575 destination[offset] = FLOAT_BYTES[0];576 destination[offset + 1] = FLOAT_BYTES[1];577 destination[offset + 2] = FLOAT_BYTES[2];578 destination[offset + 3] = FLOAT_BYTES[3];579 destination[offset + 4] = FLOAT_BYTES[4];580 destination[offset + 5] = FLOAT_BYTES[5];581 destination[offset + 6] = FLOAT_BYTES[6];582 destination[offset + 7] = FLOAT_BYTES[7];583 return 8;584 }585};586 587class Binary extends BSONValue {588 get _bsontype() {589 return 'Binary';590 }591 constructor(buffer, subType) {592 super();593 if (!(buffer == null) &&594 typeof buffer === 'string' &&595 !ArrayBuffer.isView(buffer) &&596 !isAnyArrayBuffer(buffer) &&597 !Array.isArray(buffer)) {598 throw new BSONError('Binary can only be constructed from Uint8Array or number[]');599 }600 this.sub_type = subType ?? Binary.BSON_BINARY_SUBTYPE_DEFAULT;601 if (buffer == null) {602 this.buffer = ByteUtils.allocate(Binary.BUFFER_SIZE);603 this.position = 0;604 }605 else {606 this.buffer = Array.isArray(buffer)607 ? ByteUtils.fromNumberArray(buffer)608 : ByteUtils.toLocalBufferType(buffer);609 this.position = this.buffer.byteLength;610 }611 }612 put(byteValue) {613 if (typeof byteValue === 'string' && byteValue.length !== 1) {614 throw new BSONError('only accepts single character String');615 }616 else if (typeof byteValue !== 'number' && byteValue.length !== 1)617 throw new BSONError('only accepts single character Uint8Array or Array');618 let decodedByte;619 if (typeof byteValue === 'string') {620 decodedByte = byteValue.charCodeAt(0);621 }622 else if (typeof byteValue === 'number') {623 decodedByte = byteValue;624 }625 else {626 decodedByte = byteValue[0];627 }628 if (decodedByte < 0 || decodedByte > 255) {629 throw new BSONError('only accepts number in a valid unsigned byte range 0-255');630 }631 if (this.buffer.byteLength > this.position) {632 this.buffer[this.position++] = decodedByte;633 }634 else {635 const newSpace = ByteUtils.allocate(Binary.BUFFER_SIZE + this.buffer.length);636 newSpace.set(this.buffer, 0);637 this.buffer = newSpace;638 this.buffer[this.position++] = decodedByte;639 }640 }641 write(sequence, offset) {642 offset = typeof offset === 'number' ? offset : this.position;643 if (this.buffer.byteLength < offset + sequence.length) {644 const newSpace = ByteUtils.allocate(this.buffer.byteLength + sequence.length);645 newSpace.set(this.buffer, 0);646 this.buffer = newSpace;647 }648 if (ArrayBuffer.isView(sequence)) {649 this.buffer.set(ByteUtils.toLocalBufferType(sequence), offset);650 this.position =651 offset + sequence.byteLength > this.position ? offset + sequence.length : this.position;652 }653 else if (typeof sequence === 'string') {654 throw new BSONError('input cannot be string');655 }656 }657 read(position, length) {658 length = length && length > 0 ? length : this.position;659 const end = position + length;660 return this.buffer.subarray(position, end > this.position ? this.position : end);661 }662 value() {663 return this.buffer.length === this.position664 ? this.buffer665 : this.buffer.subarray(0, this.position);666 }667 length() {668 return this.position;669 }670 toJSON() {671 return ByteUtils.toBase64(this.buffer.subarray(0, this.position));672 }673 toString(encoding) {674 if (encoding === 'hex')675 return ByteUtils.toHex(this.buffer.subarray(0, this.position));676 if (encoding === 'base64')677 return ByteUtils.toBase64(this.buffer.subarray(0, this.position));678 if (encoding === 'utf8' || encoding === 'utf-8')679 return ByteUtils.toUTF8(this.buffer, 0, this.position, false);680 return ByteUtils.toUTF8(this.buffer, 0, this.position, false);681 }682 toExtendedJSON(options) {683 options = options || {};684 if (this.sub_type === Binary.SUBTYPE_VECTOR) {685 validateBinaryVector(this);686 }687 const base64String = ByteUtils.toBase64(this.buffer);688 const subType = Number(this.sub_type).toString(16);689 if (options.legacy) {690 return {691 $binary: base64String,692 $type: subType.length === 1 ? '0' + subType : subType693 };694 }695 return {696 $binary: {697 base64: base64String,698 subType: subType.length === 1 ? '0' + subType : subType699 }700 };701 }702 toUUID() {703 if (this.sub_type === Binary.SUBTYPE_UUID) {704 return new UUID(this.buffer.subarray(0, this.position));705 }706 throw new BSONError(`Binary sub_type "${this.sub_type}" is not supported for converting to UUID. Only "${Binary.SUBTYPE_UUID}" is currently supported.`);707 }708 static createFromHexString(hex, subType) {709 return new Binary(ByteUtils.fromHex(hex), subType);710 }711 static createFromBase64(base64, subType) {712 return new Binary(ByteUtils.fromBase64(base64), subType);713 }714 static fromExtendedJSON(doc, options) {715 options = options || {};716 let data;717 let type;718 if ('$binary' in doc) {719 if (options.legacy && typeof doc.$binary === 'string' && '$type' in doc) {720 type = doc.$type ? parseInt(doc.$type, 16) : 0;721 data = ByteUtils.fromBase64(doc.$binary);722 }723 else {724 if (typeof doc.$binary !== 'string') {725 type = doc.$binary.subType ? parseInt(doc.$binary.subType, 16) : 0;726 data = ByteUtils.fromBase64(doc.$binary.base64);727 }728 }729 }730 else if ('$uuid' in doc) {731 type = 4;732 data = UUID.bytesFromString(doc.$uuid);733 }734 if (!data) {735 throw new BSONError(`Unexpected Binary Extended JSON format ${JSON.stringify(doc)}`);736 }737 return type === BSON_BINARY_SUBTYPE_UUID_NEW ? new UUID(data) : new Binary(data, type);738 }739 inspect(depth, options, inspect) {740 inspect ??= defaultInspect;741 const base64 = ByteUtils.toBase64(this.buffer.subarray(0, this.position));742 const base64Arg = inspect(base64, options);743 const subTypeArg = inspect(this.sub_type, options);744 return `Binary.createFromBase64(${base64Arg}, ${subTypeArg})`;745 }746 toInt8Array() {747 if (this.sub_type !== Binary.SUBTYPE_VECTOR) {748 throw new BSONError('Binary sub_type is not Vector');749 }750 if (this.buffer[0] !== Binary.VECTOR_TYPE.Int8) {751 throw new BSONError('Binary datatype field is not Int8');752 }753 validateBinaryVector(this);754 return new Int8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));755 }756 toFloat32Array() {757 if (this.sub_type !== Binary.SUBTYPE_VECTOR) {758 throw new BSONError('Binary sub_type is not Vector');759 }760 if (this.buffer[0] !== Binary.VECTOR_TYPE.Float32) {761 throw new BSONError('Binary datatype field is not Float32');762 }763 validateBinaryVector(this);764 const floatBytes = new Uint8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));765 if (NumberUtils.isBigEndian)766 ByteUtils.swap32(floatBytes);767 return new Float32Array(floatBytes.buffer);768 }769 toPackedBits() {770 if (this.sub_type !== Binary.SUBTYPE_VECTOR) {771 throw new BSONError('Binary sub_type is not Vector');772 }773 if (this.buffer[0] !== Binary.VECTOR_TYPE.PackedBit) {774 throw new BSONError('Binary datatype field is not packed bit');775 }776 validateBinaryVector(this);777 return new Uint8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));778 }779 toBits() {780 if (this.sub_type !== Binary.SUBTYPE_VECTOR) {781 throw new BSONError('Binary sub_type is not Vector');782 }783 if (this.buffer[0] !== Binary.VECTOR_TYPE.PackedBit) {784 throw new BSONError('Binary datatype field is not packed bit');785 }786 validateBinaryVector(this);787 const byteCount = this.length() - 2;788 const bitCount = byteCount * 8 - this.buffer[1];789 const bits = new Int8Array(bitCount);790 for (let bitOffset = 0; bitOffset < bits.length; bitOffset++) {791 const byteOffset = (bitOffset / 8) | 0;792 const byte = this.buffer[byteOffset + 2];793 const shift = 7 - (bitOffset % 8);794 const bit = (byte >> shift) & 1;795 bits[bitOffset] = bit;796 }797 return bits;798 }799 static fromInt8Array(array) {800 const buffer = ByteUtils.allocate(array.byteLength + 2);801 buffer[0] = Binary.VECTOR_TYPE.Int8;802 buffer[1] = 0;803 const intBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);804 buffer.set(intBytes, 2);805 const bin = new this(buffer, this.SUBTYPE_VECTOR);806 validateBinaryVector(bin);807 return bin;808 }809 static fromFloat32Array(array) {810 const binaryBytes = ByteUtils.allocate(array.byteLength + 2);811 binaryBytes[0] = Binary.VECTOR_TYPE.Float32;812 binaryBytes[1] = 0;813 const floatBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);814 binaryBytes.set(floatBytes, 2);815 if (NumberUtils.isBigEndian)816 ByteUtils.swap32(new Uint8Array(binaryBytes.buffer, 2));817 const bin = new this(binaryBytes, this.SUBTYPE_VECTOR);818 validateBinaryVector(bin);819 return bin;820 }821 static fromPackedBits(array, padding = 0) {822 const buffer = ByteUtils.allocate(array.byteLength + 2);823 buffer[0] = Binary.VECTOR_TYPE.PackedBit;824 buffer[1] = padding;825 buffer.set(array, 2);826 const bin = new this(buffer, this.SUBTYPE_VECTOR);827 validateBinaryVector(bin);828 return bin;829 }830 static fromBits(bits) {831 const byteLength = (bits.length + 7) >>> 3;832 const bytes = new Uint8Array(byteLength + 2);833 bytes[0] = Binary.VECTOR_TYPE.PackedBit;834 const remainder = bits.length % 8;835 bytes[1] = remainder === 0 ? 0 : 8 - remainder;836 for (let bitOffset = 0; bitOffset < bits.length; bitOffset++) {837 const byteOffset = bitOffset >>> 3;838 const bit = bits[bitOffset];839 if (bit !== 0 && bit !== 1) {840 throw new BSONError(`Invalid bit value at ${bitOffset}: must be 0 or 1, found ${bits[bitOffset]}`);841 }842 if (bit === 0)843 continue;844 const shift = 7 - (bitOffset % 8);845 bytes[byteOffset + 2] |= bit << shift;846 }847 return new this(bytes, Binary.SUBTYPE_VECTOR);848 }849}850Binary.BSON_BINARY_SUBTYPE_DEFAULT = 0;851Binary.BUFFER_SIZE = 256;852Binary.SUBTYPE_DEFAULT = 0;853Binary.SUBTYPE_FUNCTION = 1;854Binary.SUBTYPE_BYTE_ARRAY = 2;855Binary.SUBTYPE_UUID_OLD = 3;856Binary.SUBTYPE_UUID = 4;857Binary.SUBTYPE_MD5 = 5;858Binary.SUBTYPE_ENCRYPTED = 6;859Binary.SUBTYPE_COLUMN = 7;860Binary.SUBTYPE_SENSITIVE = 8;861Binary.SUBTYPE_VECTOR = 9;862Binary.SUBTYPE_USER_DEFINED = 128;863Binary.VECTOR_TYPE = Object.freeze({864 Int8: 0x03,865 Float32: 0x27,866 PackedBit: 0x10867});868function validateBinaryVector(vector) {869 if (vector.sub_type !== Binary.SUBTYPE_VECTOR)870 return;871 const size = vector.position;872 const datatype = vector.buffer[0];873 const padding = vector.buffer[1];874 if ((datatype === Binary.VECTOR_TYPE.Float32 || datatype === Binary.VECTOR_TYPE.Int8) &&875 padding !== 0) {876 throw new BSONError('Invalid Vector: padding must be zero for int8 and float32 vectors');877 }878 if (datatype === Binary.VECTOR_TYPE.Float32) {879 if (size !== 0 && size - 2 !== 0 && (size - 2) % 4 !== 0) {880 throw new BSONError('Invalid Vector: Float32 vector must contain a multiple of 4 bytes');881 }882 }883 if (datatype === Binary.VECTOR_TYPE.PackedBit && padding !== 0 && size === 2) {884 throw new BSONError('Invalid Vector: padding must be zero for packed bit vectors that are empty');885 }886 if (datatype === Binary.VECTOR_TYPE.PackedBit && padding > 7) {887 throw new BSONError(`Invalid Vector: padding must be a value between 0 and 7. found: ${padding}`);888 }889}890const UUID_BYTE_LENGTH = 16;891const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;892const UUID_WITH_DASHES = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i;893class UUID extends Binary {894 constructor(input) {895 let bytes;896 if (input == null) {897 bytes = UUID.generate();898 }899 else if (input instanceof UUID) {900 bytes = ByteUtils.toLocalBufferType(new Uint8Array(input.buffer));901 }902 else if (ArrayBuffer.isView(input) && input.byteLength === UUID_BYTE_LENGTH) {903 bytes = ByteUtils.toLocalBufferType(input);904 }905 else if (typeof input === 'string') {906 bytes = UUID.bytesFromString(input);907 }908 else {909 throw new BSONError('Argument passed in UUID constructor must be a UUID, a 16 byte Buffer or a 32/36 character hex string (dashes excluded/included, format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).');910 }911 super(bytes, BSON_BINARY_SUBTYPE_UUID_NEW);912 }913 get id() {914 return this.buffer;915 }916 set id(value) {917 this.buffer = value;918 }919 toHexString(includeDashes = true) {920 if (includeDashes) {921 return [922 ByteUtils.toHex(this.buffer.subarray(0, 4)),923 ByteUtils.toHex(this.buffer.subarray(4, 6)),924 ByteUtils.toHex(this.buffer.subarray(6, 8)),925 ByteUtils.toHex(this.buffer.subarray(8, 10)),926 ByteUtils.toHex(this.buffer.subarray(10, 16))927 ].join('-');928 }929 return ByteUtils.toHex(this.buffer);930 }931 toString(encoding) {932 if (encoding === 'hex')933 return ByteUtils.toHex(this.id);934 if (encoding === 'base64')935 return ByteUtils.toBase64(this.id);936 return this.toHexString();937 }938 toJSON() {939 return this.toHexString();940 }941 equals(otherId) {942 if (!otherId) {943 return false;944 }945 if (otherId instanceof UUID) {946 return ByteUtils.equals(otherId.id, this.id);947 }948 try {949 return ByteUtils.equals(new UUID(otherId).id, this.id);950 }951 catch {952 return false;953 }954 }955 toBinary() {956 return new Binary(this.id, Binary.SUBTYPE_UUID);957 }958 static generate() {959 const bytes = ByteUtils.randomBytes(UUID_BYTE_LENGTH);960 bytes[6] = (bytes[6] & 0x0f) | 0x40;961 bytes[8] = (bytes[8] & 0x3f) | 0x80;962 return bytes;963 }964 static isValid(input) {965 if (!input) {966 return false;967 }968 if (typeof input === 'string') {969 return UUID.isValidUUIDString(input);970 }971 if (isUint8Array(input)) {972 return input.byteLength === UUID_BYTE_LENGTH;973 }974 return (input._bsontype === 'Binary' &&975 input.sub_type === this.SUBTYPE_UUID &&976 input.buffer.byteLength === 16);977 }978 static createFromHexString(hexString) {979 const buffer = UUID.bytesFromString(hexString);980 return new UUID(buffer);981 }982 static createFromBase64(base64) {983 return new UUID(ByteUtils.fromBase64(base64));984 }985 static bytesFromString(representation) {986 if (!UUID.isValidUUIDString(representation)) {987 throw new BSONError('UUID string representation must be 32 hex digits or canonical hyphenated representation');988 }989 return ByteUtils.fromHex(representation.replace(/-/g, ''));990 }991 static isValidUUIDString(representation) {992 return UUID_WITHOUT_DASHES.test(representation) || UUID_WITH_DASHES.test(representation);993 }994 inspect(depth, options, inspect) {995 inspect ??= defaultInspect;996 return `new UUID(${inspect(this.toHexString(), options)})`;997 }998}999 1000class Code extends BSONValue {1001 get _bsontype() {1002 return 'Code';1003 }1004 constructor(code, scope) {1005 super();1006 this.code = code.toString();1007 this.scope = scope ?? null;1008 }1009 toJSON() {1010 if (this.scope != null) {1011 return { code: this.code, scope: this.scope };1012 }1013 return { code: this.code };1014 }1015 toExtendedJSON() {1016 if (this.scope) {1017 return { $code: this.code, $scope: this.scope };1018 }1019 return { $code: this.code };1020 }1021 static fromExtendedJSON(doc) {1022 return new Code(doc.$code, doc.$scope);1023 }1024 inspect(depth, options, inspect) {1025 inspect ??= defaultInspect;1026 let parametersString = inspect(this.code, options);1027 const multiLineFn = parametersString.includes('\n');1028 if (this.scope != null) {1029 parametersString += `,${multiLineFn ? '\n' : ' '}${inspect(this.scope, options)}`;1030 }1031 const endingNewline = multiLineFn && this.scope === null;1032 return `new Code(${multiLineFn ? '\n' : ''}${parametersString}${endingNewline ? '\n' : ''})`;1033 }1034}1035 1036function isDBRefLike(value) {1037 return (value != null &&1038 typeof value === 'object' &&1039 '$id' in value &&1040 value.$id != null &&1041 '$ref' in value &&1042 typeof value.$ref === 'string' &&1043 (!('$db' in value) || ('$db' in value && typeof value.$db === 'string')));1044}1045class DBRef extends BSONValue {1046 get _bsontype() {1047 return 'DBRef';1048 }1049 constructor(collection, oid, db, fields) {1050 super();1051 const parts = collection.split('.');1052 if (parts.length === 2) {1053 db = parts.shift();1054 collection = parts.shift();1055 }1056 this.collection = collection;1057 this.oid = oid;1058 this.db = db;1059 this.fields = fields || {};1060 }1061 get namespace() {1062 return this.collection;1063 }1064 set namespace(value) {1065 this.collection = value;1066 }1067 toJSON() {1068 const o = Object.assign({1069 $ref: this.collection,1070 $id: this.oid1071 }, this.fields);1072 if (this.db != null)1073 o.$db = this.db;1074 return o;1075 }1076 toExtendedJSON(options) {1077 options = options || {};1078 let o = {1079 $ref: this.collection,1080 $id: this.oid1081 };1082 if (options.legacy) {1083 return o;1084 }1085 if (this.db)1086 o.$db = this.db;1087 o = Object.assign(o, this.fields);1088 return o;1089 }1090 static fromExtendedJSON(doc) {1091 const copy = Object.assign({}, doc);1092 delete copy.$ref;1093 delete copy.$id;1094 delete copy.$db;1095 return new DBRef(doc.$ref, doc.$id, doc.$db, copy);1096 }1097 inspect(depth, options, inspect) {1098 inspect ??= defaultInspect;1099 const args = [1100 inspect(this.namespace, options),1101 inspect(this.oid, options),1102 ...(this.db ? [inspect(this.db, options)] : []),1103 ...(Object.keys(this.fields).length > 0 ? [inspect(this.fields, options)] : [])1104 ];1105 args[1] = inspect === defaultInspect ? `new ObjectId(${args[1]})` : args[1];1106 return `new DBRef(${args.join(', ')})`;1107 }1108}1109 1110function removeLeadingZerosAndExplicitPlus(str) {1111 if (str === '') {1112 return str;1113 }1114 let startIndex = 0;1115 const isNegative = str[startIndex] === '-';1116 const isExplicitlyPositive = str[startIndex] === '+';1117 if (isExplicitlyPositive || isNegative) {1118 startIndex += 1;1119 }1120 let foundInsignificantZero = false;1121 for (; startIndex < str.length && str[startIndex] === '0'; ++startIndex) {1122 foundInsignificantZero = true;1123 }1124 if (!foundInsignificantZero) {1125 return isExplicitlyPositive ? str.slice(1) : str;1126 }1127 return `${isNegative ? '-' : ''}${str.length === startIndex ? '0' : str.slice(startIndex)}`;1128}1129function validateStringCharacters(str, radix) {1130 radix = radix ?? 10;1131 const validCharacters = '0123456789abcdefghijklmnopqrstuvwxyz'.slice(0, radix);1132 const regex = new RegExp(`[^-+${validCharacters}]`, 'i');1133 return regex.test(str) ? false : str;1134}1135 1136let wasm = undefined;1137try {1138 wasm = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 13, 2, 96, 0, 1, 127, 96, 4, 127, 127, 127, 127, 1, 127, 3, 7, 6, 0, 1, 1, 1, 1, 1, 6, 6, 1, 127, 1, 65, 0, 11, 7, 50, 6, 3, 109, 117, 108, 0, 1, 5, 100, 105, 118, 95, 115, 0, 2, 5, 100, 105, 118, 95, 117, 0, 3, 5, 114, 101, 109, 95, 115, 0, 4, 5, 114, 101, 109, 95, 117, 0, 5, 8, 103, 101, 116, 95, 104, 105, 103, 104, 0, 0, 10, 191, 1, 6, 4, 0, 35, 0, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 126, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 127, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 128, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 129, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 130, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11])), {}).exports;1139}1140catch {1141}1142const TWO_PWR_16_DBL = 1 << 16;1143const TWO_PWR_24_DBL = 1 << 24;1144const TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;1145const TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;1146const TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;1147const INT_CACHE = {};1148const UINT_CACHE = {};1149const MAX_INT64_STRING_LENGTH = 20;1150const DECIMAL_REG_EX = /^(\+?0|(\+|-)?[1-9][0-9]*)$/;1151class Long extends BSONValue {1152 get _bsontype() {1153 return 'Long';1154 }1155 get __isLong__() {1156 return true;1157 }1158 constructor(lowOrValue = 0, highOrUnsigned, unsigned) {1159 super();1160 const unsignedBool = typeof highOrUnsigned === 'boolean' ? highOrUnsigned : Boolean(unsigned);1161 const high = typeof highOrUnsigned === 'number' ? highOrUnsigned : 0;1162 const res = typeof lowOrValue === 'string'1163 ? Long.fromString(lowOrValue, unsignedBool)1164 : typeof lowOrValue === 'bigint'1165 ? Long.fromBigInt(lowOrValue, unsignedBool)1166 : { low: lowOrValue | 0, high: high | 0, unsigned: unsignedBool };1167 this.low = res.low;1168 this.high = res.high;1169 this.unsigned = res.unsigned;1170 }1171 static fromBits(lowBits, highBits, unsigned) {1172 return new Long(lowBits, highBits, unsigned);1173 }1174 static fromInt(value, unsigned) {1175 let obj, cachedObj, cache;1176 if (unsigned) {1177 value >>>= 0;1178 if ((cache = 0 <= value && value < 256)) {1179 cachedObj = UINT_CACHE[value];1180 if (cachedObj)1181 return cachedObj;1182 }1183 obj = Long.fromBits(value, (value | 0) < 0 ? -1 : 0, true);1184 if (cache)1185 UINT_CACHE[value] = obj;1186 return obj;1187 }1188 else {1189 value |= 0;1190 if ((cache = -128 <= value && value < 128)) {1191 cachedObj = INT_CACHE[value];1192 if (cachedObj)1193 return cachedObj;1194 }1195 obj = Long.fromBits(value, value < 0 ? -1 : 0, false);1196 if (cache)1197 INT_CACHE[value] = obj;1198 return obj;1199 }1200 }