mongodb
Version:
The official MongoDB driver for Node.js
173 lines (161 loc) • 5.39 kB
text/typescript
/* eslint-disable no-restricted-imports */
import { BSON, type DeserializeOptions, NumberUtils, type SerializeOptions } from 'bson';
export {
Binary,
BSON,
BSONError,
BSONRegExp,
BSONSymbol,
BSONType,
ByteUtils,
calculateObjectSize,
Code,
DBRef,
Decimal128,
deserialize,
type DeserializeOptions,
Document,
Double,
EJSON,
EJSONOptions,
Int32,
Long,
MaxKey,
MinKey,
NumberUtils,
ObjectId,
type ObjectIdLike,
serialize,
Timestamp,
UUID
} from 'bson';
/** @internal */
export type BSONElement = BSON.OnDemand['BSONElement'];
export function parseToElementsToArray(bytes: Uint8Array, offset?: number): BSONElement[] {
const res = BSON.onDemand.parseToElements(bytes, offset);
return Array.isArray(res) ? res : [...res];
}
// validates buffer inputs, used for read operations
const validateBufferInputs = (buffer: Uint8Array, offset: number, length: number) => {
if (offset < 0 || offset + length > buffer.length) {
throw new RangeError(
`Attempt to access memory outside buffer bounds: buffer length: ${buffer.length}, offset: ${offset}, length: ${length}`
);
}
};
// readInt32LE, reads a 32-bit integer from buffer at given offset
// throws if offset is out of bounds
export const readInt32LE = (buffer: Uint8Array, offset: number): number => {
validateBufferInputs(buffer, offset, 4);
return NumberUtils.getInt32LE(buffer, offset);
};
export const setUint32LE = (destination: Uint8Array, offset: number, value: number): 4 => {
destination[offset] = value;
value >>>= 8;
destination[offset + 1] = value;
value >>>= 8;
destination[offset + 2] = value;
value >>>= 8;
destination[offset + 3] = value;
return 4;
};
/**
* BSON Serialization options.
* @public
*/
export interface BSONSerializeOptions
extends Omit<SerializeOptions, 'index'>,
Omit<
DeserializeOptions,
| 'evalFunctions'
| 'cacheFunctions'
| 'cacheFunctionsCrc32'
| 'allowObjectSmallerThanBufferSize'
| 'index'
| 'validation'
> {
/**
* Enabling the raw option will return a [Node.js Buffer](https://nodejs.org/api/buffer.html)
* which is allocated using [allocUnsafe API](https://nodejs.org/api/buffer.html#static-method-bufferallocunsafesize).
* See this section from the [Node.js Docs here](https://nodejs.org/api/buffer.html#what-makes-bufferallocunsafe-and-bufferallocunsafeslow-unsafe)
* for more detail about what "unsafe" refers to in this context.
* If you need to maintain your own editable clone of the bytes returned for an extended life time of the process, it is recommended you allocate
* your own buffer and clone the contents:
*
* @example
* ```ts
* const raw = await collection.findOne({}, { raw: true });
* const myBuffer = Buffer.alloc(raw.byteLength);
* myBuffer.set(raw, 0);
* // Only save and use `myBuffer` beyond this point
* ```
*
* @remarks
* Please note there is a known limitation where this option cannot be used at the MongoClient level (see [NODE-3946](https://jira.mongodb.org/browse/NODE-3946)).
* It does correctly work at `Db`, `Collection`, and per operation the same as other BSON options work.
*/
raw?: boolean;
/** Enable utf8 validation when deserializing BSON documents. Defaults to true. */
enableUtf8Validation?: boolean;
}
export function pluckBSONSerializeOptions(options: BSONSerializeOptions): BSONSerializeOptions {
const {
fieldsAsRaw,
useBigInt64,
promoteValues,
promoteBuffers,
promoteLongs,
serializeFunctions,
ignoreUndefined,
bsonRegExp,
raw,
enableUtf8Validation
} = options;
return {
fieldsAsRaw,
useBigInt64,
promoteValues,
promoteBuffers,
promoteLongs,
serializeFunctions,
ignoreUndefined,
bsonRegExp,
raw,
enableUtf8Validation
};
}
/**
* Merge the given BSONSerializeOptions, preferring options over the parent's options, and
* substituting defaults for values not set.
*
* @internal
*/
export function resolveBSONOptions(
options?: BSONSerializeOptions,
parent?: { bsonOptions?: BSONSerializeOptions }
): BSONSerializeOptions {
const parentOptions = parent?.bsonOptions;
return {
raw: options?.raw ?? parentOptions?.raw ?? false,
useBigInt64: options?.useBigInt64 ?? parentOptions?.useBigInt64 ?? false,
promoteLongs: options?.promoteLongs ?? parentOptions?.promoteLongs ?? true,
promoteValues: options?.promoteValues ?? parentOptions?.promoteValues ?? true,
promoteBuffers: options?.promoteBuffers ?? parentOptions?.promoteBuffers ?? false,
ignoreUndefined: options?.ignoreUndefined ?? parentOptions?.ignoreUndefined ?? false,
bsonRegExp: options?.bsonRegExp ?? parentOptions?.bsonRegExp ?? false,
serializeFunctions: options?.serializeFunctions ?? parentOptions?.serializeFunctions ?? false,
fieldsAsRaw: options?.fieldsAsRaw ?? parentOptions?.fieldsAsRaw ?? {},
enableUtf8Validation:
options?.enableUtf8Validation ?? parentOptions?.enableUtf8Validation ?? true
};
}
/** @internal */
export function parseUtf8ValidationOption(options?: { enableUtf8Validation?: boolean }): {
utf8: { writeErrors: false } | false;
} {
const enableUtf8Validation = options?.enableUtf8Validation;
if (enableUtf8Validation === false) {
return { utf8: false };
}
return { utf8: { writeErrors: false } };
}