Aryan
Optimize full-stack VigilantRAG for Hugging Face Spaces deployment with MongoDB Atlas
4c452d5
Raw
History Blame Contribute Delete
17.7 kB
import { BSONValue } from './bson_value';
import { BSONError } from './error';
import { type InspectFn, defaultInspect } from './parser/utils';
import { ByteUtils } from './utils/byte_utils';
import { NumberUtils } from './utils/number_utils';
/** ObjectId hexString cache @internal */
const __idCache = new WeakMap(); // TODO(NODE-6549): convert this to #__id private field when target updated to ES2022
/** byte (0-255): its 2-character lowercase hex pair @internal */
const byteToHex: string[] = [];
for (let n = 0; n < 256; n++) byteToHex.push(n.toString(16).padStart(2, '0'));
/** hex char code: nibble (0-15); indices are the codes of 0-9, a-f, A-F @internal */
const hexCharCodeToNibble = new Int8Array(103);
for (let c = 48; c <= 57; c++) hexCharCodeToNibble[c] = c - 48; // '0'-'9'
for (let c = 65; c <= 70; c++) hexCharCodeToNibble[c] = c - 55; // 'A'-'F'
for (let c = 97; c <= 102; c++) hexCharCodeToNibble[c] = c - 87; // 'a'-'f'
/** @public */
export interface ObjectIdLike {
id: string | Uint8Array;
__id?: string;
toHexString(): string;
}
/** @public */
export interface ObjectIdExtended {
$oid: string;
}
/**
* A class representation of the BSON ObjectId type.
* @public
* @category BSONType
*/
export class ObjectId extends BSONValue {
get _bsontype(): 'ObjectId' {
return 'ObjectId';
}
/** @internal */
private static index = 0;
/** Unique sequence for the current process (initialized on first use)
* @internal
*/
private static PROCESS_UNIQUE: Uint8Array | null = null;
/** @internal */
private static resetState = (): void => {
this.index = Math.floor(Math.random() * 0x1000000);
// PROCESS_UNIQUE is (re)generated lazily on first use rather than here, so that merely loading
// BSON never calls secure random at module-evaluation time. Runtimes such as Cloudflare Workers
// forbid generating random values in the global scope.
this.PROCESS_UNIQUE = null;
};
static {
this.resetState();
// https://nodejs.org/api/v8.html#startup-snapshot-api
// @ts-expect-error Node.js types not present since this is an optional API
const { startupSnapshot } = globalThis?.process?.getBuiltinModule?.('v8') ?? {};
if (startupSnapshot?.isBuildingSnapshot?.()) {
startupSnapshot?.addDeserializeCallback?.(this.resetState);
}
}
static cacheHexString: boolean;
/**
* The 12 ObjectId bytes packed as four 24-bit integers (bytes 0-2, 3-5, 6-8, 9-11).
* The 24-bit width keeps each value inside V8's small-integer (Smi) range so it stays stored
* inline, which keeps the object small. The fields are enumerable own properties, so two
* ObjectIds with the same bytes stay equal under structural comparison such as deepStrictEqual.
* @internal
*/
private i0!: number;
/** @internal */
private i1!: number;
/** @internal */
private i2!: number;
/** @internal */
private i3!: number;
/** Pack 12 bytes into the four integer fields. @internal */
private setFromBytes(b: Uint8Array, offset = 0): void {
this.i0 = (b[offset] << 16) | (b[offset + 1] << 8) | b[offset + 2];
this.i1 = (b[offset + 3] << 16) | (b[offset + 4] << 8) | b[offset + 5];
this.i2 = (b[offset + 6] << 16) | (b[offset + 7] << 8) | b[offset + 8];
this.i3 = (b[offset + 9] << 16) | (b[offset + 10] << 8) | b[offset + 11];
}
/**
* Pack a validated 24-character hex string into the four integer fields. The caller must have
* already validated the string; every character is assumed to be a hex digit.
* @internal
*/
private setFromHex(s: string): void {
const t = hexCharCodeToNibble;
this.i0 =
(t[s.charCodeAt(0)] << 20) |
(t[s.charCodeAt(1)] << 16) |
(t[s.charCodeAt(2)] << 12) |
(t[s.charCodeAt(3)] << 8) |
(t[s.charCodeAt(4)] << 4) |
t[s.charCodeAt(5)];
this.i1 =
(t[s.charCodeAt(6)] << 20) |
(t[s.charCodeAt(7)] << 16) |
(t[s.charCodeAt(8)] << 12) |
(t[s.charCodeAt(9)] << 8) |
(t[s.charCodeAt(10)] << 4) |
t[s.charCodeAt(11)];
this.i2 =
(t[s.charCodeAt(12)] << 20) |
(t[s.charCodeAt(13)] << 16) |
(t[s.charCodeAt(14)] << 12) |
(t[s.charCodeAt(15)] << 8) |
(t[s.charCodeAt(16)] << 4) |
t[s.charCodeAt(17)];
this.i3 =
(t[s.charCodeAt(18)] << 20) |
(t[s.charCodeAt(19)] << 16) |
(t[s.charCodeAt(20)] << 12) |
(t[s.charCodeAt(21)] << 8) |
(t[s.charCodeAt(22)] << 4) |
t[s.charCodeAt(23)];
}
/** To generate a new ObjectId, use ObjectId() with no argument. */
constructor();
/**
* Create ObjectId from a 24 character hex string.
*
* @param inputId - A 24 character hex string.
*/
constructor(inputId: string);
/**
* Create ObjectId from the BSON ObjectId type.
*
* @param inputId - The BSON ObjectId type.
*/
constructor(inputId: ObjectId);
/**
* Create ObjectId from the object type that has the toHexString method.
*
* @param inputId - The ObjectIdLike type.
*/
constructor(inputId: ObjectIdLike);
/**
* Create ObjectId from a 12 byte binary Buffer.
*
* @param inputId - A 12 byte binary Buffer.
*/
constructor(inputId: Uint8Array);
/**
* Implementation overload.
*
* @param inputId - All input types that are used in the constructor implementation.
*/
constructor(inputId?: string | ObjectId | ObjectIdLike | Uint8Array);
/**
* Read 12 bytes from `source` starting at `offset` directly into the packed fields.
* Used by the deserializer on a hot path.
* @internal
*/
constructor(source: Uint8Array, offset: number);
/**
* Create a new ObjectId.
*
* @param inputId - An input value to create a new ObjectId from.
*/
constructor(inputId?: string | ObjectId | ObjectIdLike | Uint8Array, offset?: number) {
super();
if (typeof offset === 'number') {
// Fast path used by the deserializer: read the 12 bytes directly from source at offset.
this.setFromBytes(inputId as Uint8Array, offset);
return;
}
// workingId is set based on type of input and whether valid id exists for the input
let workingId;
if (typeof inputId === 'object' && inputId && 'id' in inputId) {
if (
ObjectId.is(inputId) &&
typeof inputId.i0 === 'number' &&
typeof inputId.i1 === 'number' &&
typeof inputId.i2 === 'number' &&
typeof inputId.i3 === 'number'
) {
// Same-build ObjectId: copy the packed fields directly. The general path below would
// hit the id getter (which allocates) and then re-decode a hex round trip.
this.i0 = inputId.i0;
this.i1 = inputId.i1;
this.i2 = inputId.i2;
this.i3 = inputId.i3;
return;
}
if (typeof inputId.id !== 'string' && !ArrayBuffer.isView(inputId.id)) {
throw new BSONError('Argument passed in must have an id that is of type string or Buffer');
}
if ('toHexString' in inputId && typeof inputId.toHexString === 'function') {
workingId = ByteUtils.fromHex(inputId.toHexString());
} else {
workingId = inputId.id;
}
} else {
workingId = inputId;
}
// The following cases use workingId to construct an ObjectId
if (workingId == null) {
// The most common use case (blank id, new objectId instance):
// generate a new id directly into the packed fields.
const time = Math.floor(Date.now() / 1000);
const inc = ObjectId.getInc();
const pu = (ObjectId.PROCESS_UNIQUE ??= ByteUtils.randomBytes(5));
this.i0 = (time >>> 8) & 0xffffff;
this.i1 = ((time & 0xff) << 16) | (pu[0] << 8) | pu[1];
this.i2 = (pu[2] << 16) | (pu[3] << 8) | pu[4];
this.i3 = inc & 0xffffff;
} else if (ArrayBuffer.isView(workingId) && workingId.byteLength === 12) {
// Normalize a non-Uint8Array view (DataView, Int8Array, ...) to a byte buffer so its
// bytes are read correctly.
this.setFromBytes(
workingId instanceof Uint8Array ? workingId : ByteUtils.toLocalBufferType(workingId)
);
} else if (typeof workingId === 'string') {
if (ObjectId.validateHexString(workingId)) {
this.setFromHex(workingId);
// If we are caching the hex string
if (ObjectId.cacheHexString) {
__idCache.set(this, workingId);
}
} else {
throw new BSONError(
'input must be a 24 character hex string, 12 byte Uint8Array, or an integer'
);
}
} else {
throw new BSONError('Argument passed in does not match the accepted types');
}
}
/**
* The ObjectId bytes, rebuilt from the packed integer fields on each access. Every read
* returns a freshly allocated 12-byte buffer.
* @readonly
*/
get id(): Uint8Array {
const b = ByteUtils.allocateUnsafe(12);
b[0] = (this.i0 >>> 16) & 0xff;
b[1] = (this.i0 >>> 8) & 0xff;
b[2] = this.i0 & 0xff;
b[3] = (this.i1 >>> 16) & 0xff;
b[4] = (this.i1 >>> 8) & 0xff;
b[5] = this.i1 & 0xff;
b[6] = (this.i2 >>> 16) & 0xff;
b[7] = (this.i2 >>> 8) & 0xff;
b[8] = this.i2 & 0xff;
b[9] = (this.i3 >>> 16) & 0xff;
b[10] = (this.i3 >>> 8) & 0xff;
b[11] = this.i3 & 0xff;
return b;
}
set id(value: Uint8Array) {
const bytes = value instanceof Uint8Array ? value : ByteUtils.toLocalBufferType(value);
this.setFromBytes(bytes);
if (ObjectId.cacheHexString) {
__idCache.set(this, ByteUtils.toHex(bytes));
}
}
/**
* @internal
* Validates the input string is a valid hex representation of an ObjectId.
*/
private static validateHexString(string: string): boolean {
if (string?.length !== 24) return false;
for (let i = 0; i < 24; i++) {
const char = string.charCodeAt(i);
if (
// Check for ASCII 0-9
(char >= 48 && char <= 57) ||
// Check for ASCII a-f
(char >= 97 && char <= 102) ||
// Check for ASCII A-F
(char >= 65 && char <= 70)
) {
continue;
}
return false;
}
return true;
}
/** Returns the ObjectId id as a 24 lowercase character hex string representation */
toHexString(): string {
if (ObjectId.cacheHexString) {
const __id = __idCache.get(this);
if (__id) return __id;
}
// Encode the four packed integers to hex via a byte->pair lookup table.
const i0 = this.i0;
const i1 = this.i1;
const i2 = this.i2;
const i3 = this.i3;
const hexString =
byteToHex[(i0 >>> 16) & 0xff] +
byteToHex[(i0 >>> 8) & 0xff] +
byteToHex[i0 & 0xff] +
byteToHex[(i1 >>> 16) & 0xff] +
byteToHex[(i1 >>> 8) & 0xff] +
byteToHex[i1 & 0xff] +
byteToHex[(i2 >>> 16) & 0xff] +
byteToHex[(i2 >>> 8) & 0xff] +
byteToHex[i2 & 0xff] +
byteToHex[(i3 >>> 16) & 0xff] +
byteToHex[(i3 >>> 8) & 0xff] +
byteToHex[i3 & 0xff];
if (ObjectId.cacheHexString) {
__idCache.set(this, hexString);
}
return hexString;
}
/**
* Update the ObjectId index
* @internal
*/
private static getInc(): number {
return (ObjectId.index = (ObjectId.index + 1) % 0x1000000);
}
/**
* Generate a 12 byte id buffer used in ObjectId's
*
* @param time - pass in a second based timestamp.
*/
static generate(time?: number): Uint8Array {
if ('number' !== typeof time) {
time = Math.floor(Date.now() / 1000);
}
const inc = ObjectId.getInc();
const buffer = ByteUtils.allocateUnsafe(12);
// 4-byte timestamp
NumberUtils.setInt32BE(buffer, 0, time);
// 5-byte process unique (generated lazily on first use, see NODE-7667)
const PROCESS_UNIQUE = (this.PROCESS_UNIQUE ??= ByteUtils.randomBytes(5));
buffer[4] = PROCESS_UNIQUE[0];
buffer[5] = PROCESS_UNIQUE[1];
buffer[6] = PROCESS_UNIQUE[2];
buffer[7] = PROCESS_UNIQUE[3];
buffer[8] = PROCESS_UNIQUE[4];
// 3-byte counter
buffer[11] = inc & 0xff;
buffer[10] = (inc >>> 8) & 0xff;
buffer[9] = (inc >>> 16) & 0xff;
return buffer;
}
/**
* Converts the id into a 24 character hex string for printing, unless encoding is provided.
* @param encoding - hex or base64
*/
toString(encoding?: 'hex' | 'base64'): string {
if (encoding === 'base64') return ByteUtils.toBase64(this.id);
if (encoding === 'hex') return this.toHexString();
return this.toHexString();
}
/** Converts to its JSON the 24 character hex string representation. */
toJSON(): string {
return this.toHexString();
}
/** @internal */
private static is(variable: unknown): variable is ObjectId {
return (
variable != null &&
typeof variable === 'object' &&
'_bsontype' in variable &&
variable._bsontype === 'ObjectId'
);
}
/**
* Compares the equality of this ObjectId with `otherID`.
*
* @param otherId - ObjectId instance to compare against.
*/
equals(otherId: string | ObjectId | ObjectIdLike | undefined | null): boolean {
if (otherId === undefined || otherId === null) {
return false;
}
if (
ObjectId.is(otherId) &&
typeof otherId.i0 === 'number' &&
typeof otherId.i1 === 'number' &&
typeof otherId.i2 === 'number' &&
typeof otherId.i3 === 'number'
) {
// Same-build ObjectId (all four packed fields present): compare them directly. i3 (the
// counter / low bytes) differs most often between two ids, so checking it first fails fast.
return (
this.i3 === otherId.i3 &&
this.i0 === otherId.i0 &&
this.i1 === otherId.i1 &&
this.i2 === otherId.i2
);
}
if (typeof otherId === 'string') {
return otherId.toLowerCase() === this.toHexString();
}
if (typeof otherId === 'object' && typeof otherId.toHexString === 'function') {
// ObjectId-like values, and ObjectIds from a different bson build, compare by their
// public hex representation.
const otherIdString = otherId.toHexString();
const thisIdString = this.toHexString();
return typeof otherIdString === 'string' && otherIdString.toLowerCase() === thisIdString;
}
return false;
}
/** Returns the generation date (accurate up to the second) that this ID was generated. */
getTimestamp(): Date {
const timestamp = new Date();
// Bytes 0-3 (the big-endian timestamp) are i0's three bytes followed by i1's top byte.
const time = this.i0 * 0x100 + (this.i1 >>> 16);
timestamp.setTime(time * 1000);
return timestamp;
}
/** @internal */
static createPk(): ObjectId {
return new ObjectId();
}
/** @internal */
serializeInto(uint8array: Uint8Array, index: number): 12 {
uint8array[index] = (this.i0 >>> 16) & 0xff;
uint8array[index + 1] = (this.i0 >>> 8) & 0xff;
uint8array[index + 2] = this.i0 & 0xff;
uint8array[index + 3] = (this.i1 >>> 16) & 0xff;
uint8array[index + 4] = (this.i1 >>> 8) & 0xff;
uint8array[index + 5] = this.i1 & 0xff;
uint8array[index + 6] = (this.i2 >>> 16) & 0xff;
uint8array[index + 7] = (this.i2 >>> 8) & 0xff;
uint8array[index + 8] = this.i2 & 0xff;
uint8array[index + 9] = (this.i3 >>> 16) & 0xff;
uint8array[index + 10] = (this.i3 >>> 8) & 0xff;
uint8array[index + 11] = this.i3 & 0xff;
return 12;
}
/**
* Creates an ObjectId from a second based number, with the rest of the ObjectId zeroed out. Used for comparisons or sorting the ObjectId.
*
* @param time - an integer number representing a number of seconds.
*/
static createFromTime(time: number): ObjectId {
const buffer = ByteUtils.allocate(12);
for (let i = 11; i >= 4; i--) buffer[i] = 0;
// Encode time into first 4 bytes
NumberUtils.setInt32BE(buffer, 0, time);
// Return the new objectId
return new ObjectId(buffer);
}
/**
* Creates an ObjectId from a hex string representation of an ObjectId.
*
* @param hexString - create a ObjectId from a passed in 24 character hexstring.
*/
static createFromHexString(hexString: string): ObjectId {
if (hexString?.length !== 24) {
throw new BSONError('hex string must be 24 characters');
}
return new ObjectId(ByteUtils.fromHex(hexString));
}
/** Creates an ObjectId instance from a base64 string */
static createFromBase64(base64: string): ObjectId {
if (base64?.length !== 16) {
throw new BSONError('base64 string must be 16 characters');
}
return new ObjectId(ByteUtils.fromBase64(base64));
}
/**
* Checks if a value can be used to create a valid bson ObjectId
* @param id - any JS value
*/
static isValid(id: string | ObjectId | ObjectIdLike | Uint8Array): boolean {
if (id == null) return false;
if (typeof id === 'string') return ObjectId.validateHexString(id);
try {
new ObjectId(id);
return true;
} catch {
return false;
}
}
/** @internal */
toExtendedJSON(): ObjectIdExtended {
if (this.toHexString) return { $oid: this.toHexString() };
return { $oid: this.toString('hex') };
}
/** @internal */
static fromExtendedJSON(doc: ObjectIdExtended): ObjectId {
return new ObjectId(doc.$oid);
}
/** @internal */
private isCached(): boolean {
return ObjectId.cacheHexString && __idCache.has(this);
}
/**
* Converts to a string representation of this Id.
*
* @returns return the 24 character hex string representation.
*/
inspect(depth?: number, options?: unknown, inspect?: InspectFn): string {
inspect ??= defaultInspect;
return `new ObjectId(${inspect(this.toHexString(), options)})`;
}
}