Socket
Socket
Sign inDemoInstall

bson

Package Overview
Dependencies
Maintainers
6
Versions
162
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bson - npm Package Compare versions

Comparing version 4.7.0 to 5.0.0-alpha.0

lib/bson.bundle.js

464

bson.d.ts

@@ -1,3 +0,1 @@

import { Buffer } from 'buffer';
/**

@@ -9,3 +7,3 @@ * A class representation of the BSON Binary type.

export declare class Binary {
_bsontype: 'Binary';
get _bsontype(): 'Binary';
/* Excluded from this release type: BSON_BINARY_SUBTYPE_DEFAULT */

@@ -32,3 +30,3 @@ /** Initial buffer default size */

static readonly SUBTYPE_USER_DEFINED = 128;
buffer: Buffer;
buffer: Uint8Array;
sub_type: number;

@@ -53,3 +51,3 @@ position: number;

*/
put(byteValue: string | number | Uint8Array | Buffer | number[]): void;
put(byteValue: string | number | Uint8Array | number[]): void;
/**

@@ -79,3 +77,3 @@ * Writes a buffer or string to the binary.

toJSON(): string;
toString(format?: string): string;
toString(encoding?: 'hex' | 'base64' | 'utf8' | 'utf-8'): string;
/* Excluded from this release type: toExtendedJSON */

@@ -102,109 +100,60 @@ toUUID(): UUID;

/** @public */
export declare type BinarySequence = Uint8Array | Buffer | number[];
export declare type BinarySequence = Uint8Array | number[];
/**
* BSON default export
* @deprecated Please use named exports
* @privateRemarks
* We want to someday deprecate the default export,
* so none of the new TS types are being exported on the default
* @public
*/
declare const BSON: {
Binary: typeof Binary;
Code: typeof Code;
DBRef: typeof DBRef;
Decimal128: typeof Decimal128;
Double: typeof Double;
Int32: typeof Int32;
Long: typeof Long;
UUID: typeof UUID;
Map: MapConstructor;
MaxKey: typeof MaxKey;
MinKey: typeof MinKey;
ObjectId: typeof ObjectId;
ObjectID: typeof ObjectId;
BSONRegExp: typeof BSONRegExp;
BSONSymbol: typeof BSONSymbol;
Timestamp: typeof Timestamp;
EJSON: typeof EJSON;
setInternalBufferSize: typeof setInternalBufferSize;
serialize: typeof serialize;
serializeWithBufferAndIndex: typeof serializeWithBufferAndIndex;
deserialize: typeof deserialize;
calculateObjectSize: typeof calculateObjectSize;
deserializeStream: typeof deserializeStream;
BSONError: typeof BSONError;
BSONTypeError: typeof BSONTypeError;
};
export default BSON;
declare namespace BSON {
export {
setInternalBufferSize,
serialize,
serializeWithBufferAndIndex,
deserialize,
calculateObjectSize,
deserializeStream,
UUIDExtended,
BinaryExtended,
BinaryExtendedLegacy,
BinarySequence,
CodeExtended,
DBRefLike,
Decimal128Extended,
DoubleExtended,
EJSONOptions,
Int32Extended,
LongExtended,
MaxKeyExtended,
MinKeyExtended,
ObjectIdExtended,
ObjectIdLike,
BSONRegExpExtended,
BSONRegExpExtendedLegacy,
BSONSymbolExtended,
LongWithoutOverrides,
TimestampExtended,
TimestampOverrides,
LongWithoutOverridesClass,
SerializeOptions,
DeserializeOptions,
Code,
BSONSymbol,
DBRef,
Binary,
ObjectId,
UUID,
Long,
Timestamp,
Double,
Int32,
MinKey,
MaxKey,
BSONRegExp,
Decimal128,
BSONError,
BSONTypeError,
BSONType,
EJSON,
Document,
CalculateObjectSizeOptions
}
}
export { BSON }
/* Excluded from this release type: BSON_BINARY_SUBTYPE_BYTE_ARRAY */
/* Excluded from this release type: BSON_BINARY_SUBTYPE_COLUMN */
/* Excluded from this release type: BSON_BINARY_SUBTYPE_DEFAULT */
/* Excluded from this release type: BSON_BINARY_SUBTYPE_ENCRYPTED */
/* Excluded from this release type: BSON_BINARY_SUBTYPE_FUNCTION */
/* Excluded from this release type: BSON_BINARY_SUBTYPE_MD5 */
/* Excluded from this release type: BSON_BINARY_SUBTYPE_USER_DEFINED */
/* Excluded from this release type: BSON_BINARY_SUBTYPE_UUID */
/* Excluded from this release type: BSON_BINARY_SUBTYPE_UUID_NEW */
/* Excluded from this release type: BSON_DATA_ARRAY */
/* Excluded from this release type: BSON_DATA_BINARY */
/* Excluded from this release type: BSON_DATA_BOOLEAN */
/* Excluded from this release type: BSON_DATA_CODE */
/* Excluded from this release type: BSON_DATA_CODE_W_SCOPE */
/* Excluded from this release type: BSON_DATA_DATE */
/* Excluded from this release type: BSON_DATA_DBPOINTER */
/* Excluded from this release type: BSON_DATA_DECIMAL128 */
/* Excluded from this release type: BSON_DATA_INT */
/* Excluded from this release type: BSON_DATA_LONG */
/* Excluded from this release type: BSON_DATA_MAX_KEY */
/* Excluded from this release type: BSON_DATA_MIN_KEY */
/* Excluded from this release type: BSON_DATA_NULL */
/* Excluded from this release type: BSON_DATA_NUMBER */
/* Excluded from this release type: BSON_DATA_OBJECT */
/* Excluded from this release type: BSON_DATA_OID */
/* Excluded from this release type: BSON_DATA_REGEXP */
/* Excluded from this release type: BSON_DATA_STRING */
/* Excluded from this release type: BSON_DATA_SYMBOL */
/* Excluded from this release type: BSON_DATA_TIMESTAMP */
/* Excluded from this release type: BSON_DATA_UNDEFINED */
/* Excluded from this release type: BSON_INT32_MAX */
/* Excluded from this release type: BSON_INT32_MIN */
/* Excluded from this release type: BSON_INT64_MAX */
/* Excluded from this release type: BSON_INT64_MIN */
/** @public */

@@ -222,3 +171,3 @@ export declare class BSONError extends Error {

export declare class BSONRegExp {
_bsontype: 'BSONRegExp';
get _bsontype(): 'BSONRegExp';
pattern: string;

@@ -234,2 +183,3 @@ options: string;

/* Excluded from this release type: fromExtendedJSON */
inspect(): string;
}

@@ -257,3 +207,3 @@

export declare class BSONSymbol {
_bsontype: 'Symbol';
get _bsontype(): 'BSONSymbol';
value: string;

@@ -279,2 +229,30 @@ /**

/** @public */
export declare const BSONType: Readonly<{
readonly double: 1;
readonly string: 2;
readonly object: 3;
readonly array: 4;
readonly binData: 5;
readonly undefined: 6;
readonly objectId: 7;
readonly bool: 8;
readonly date: 9;
readonly null: 10;
readonly regex: 11;
readonly dbPointer: 12;
readonly javascript: 13;
readonly symbol: 14;
readonly javascriptWithScope: 15;
readonly int: 16;
readonly timestamp: 17;
readonly long: 18;
readonly decimal: 19;
readonly minKey: -1;
readonly maxKey: 127;
}>;
/** @public */
export declare type BSONType = typeof BSONType[keyof typeof BSONType];
/** @public */
export declare class BSONTypeError extends TypeError {

@@ -303,5 +281,5 @@ constructor(message: string);

export declare class Code {
_bsontype: 'Code';
code: string | Function;
scope?: Document;
get _bsontype(): 'Code';
code: string;
scope: Document | null;
/**

@@ -311,5 +289,5 @@ * @param code - a string or function.

*/
constructor(code: string | Function, scope?: Document);
constructor(code: string | Function, scope?: Document | null);
toJSON(): {
code: string | Function;
code: string;
scope?: Document;

@@ -324,3 +302,3 @@ };

export declare interface CodeExtended {
$code: string | Function;
$code: string;
$scope?: Document;

@@ -335,3 +313,3 @@ }

export declare class DBRef {
_bsontype: 'DBRef';
get _bsontype(): 'DBRef';
collection: string;

@@ -368,4 +346,4 @@ oid: ObjectId;

export declare class Decimal128 {
_bsontype: 'Decimal128';
readonly bytes: Buffer;
get _bsontype(): 'Decimal128';
readonly bytes: Uint8Array;
/**

@@ -375,3 +353,3 @@ * @param bytes - a buffer containing the raw Decimal128 bytes in little endian order,

*/
constructor(bytes: Buffer | string);
constructor(bytes: Uint8Array | string);
/**

@@ -403,16 +381,6 @@ * Create a Decimal128 instance from a string representation

*/
export declare function deserialize(buffer: Buffer | ArrayBufferView | ArrayBuffer, options?: DeserializeOptions): Document;
export declare function deserialize(buffer: Uint8Array, options?: DeserializeOptions): Document;
/** @public */
export declare interface DeserializeOptions {
/** evaluate functions in the BSON document scoped to the object deserialized. */
evalFunctions?: boolean;
/** cache evaluated functions for reuse. */
cacheFunctions?: boolean;
/**
* use a crc32 code for caching, otherwise use the string of the function.
* @deprecated this option to use the crc32 function never worked as intended
* due to the fact that the crc32 function itself was never implemented.
* */
cacheFunctionsCrc32?: boolean;
/** when deserializing a Long will fit it into a Number if it's smaller than 53 bits */

@@ -465,3 +433,3 @@ promoteLongs?: boolean;

*/
export declare function deserializeStream(data: Buffer | ArrayBufferView | ArrayBuffer, startIndex: number, numberOfDocuments: number, documents: Document[], docStartIndex: number, options: DeserializeOptions): number;
export declare function deserializeStream(data: Uint8Array | ArrayBuffer, startIndex: number, numberOfDocuments: number, documents: Document[], docStartIndex: number, options: DeserializeOptions): number;

@@ -479,3 +447,3 @@ /** @public */

export declare class Double {
_bsontype: 'Double';
get _bsontype(): 'Double';
value: number;

@@ -506,81 +474,35 @@ /**

/** @public */
export declare const EJSON: {
parse: typeof parse;
stringify: typeof stringify;
serialize: typeof EJSONserialize;
deserialize: typeof EJSONdeserialize;
};
/**
* EJSON parse / stringify API
* @public
* Deserializes an Extended JSON object into a plain JavaScript object with native/BSON types
*
* @param ejson - The Extended JSON object to deserialize
* @param options - Optional settings passed to the parse method
*/
export declare namespace EJSON {
export interface Options {
/** Output using the Extended JSON v1 spec */
legacy?: boolean;
/** Enable Extended JSON's `relaxed` mode, which attempts to return native JS types where possible, rather than BSON types */
relaxed?: boolean;
/**
* Disable Extended JSON's `relaxed` mode, which attempts to return BSON types where possible, rather than native JS types
* @deprecated Please use the relaxed property instead
*/
strict?: boolean;
}
/**
* Parse an Extended JSON string, constructing the JavaScript value or object described by that
* string.
*
* @example
* ```js
* const { EJSON } = require('bson');
* const text = '{ "int32": { "$numberInt": "10" } }';
*
* // prints { int32: { [String: '10'] _bsontype: 'Int32', value: '10' } }
* console.log(EJSON.parse(text, { relaxed: false }));
*
* // prints { int32: 10 }
* console.log(EJSON.parse(text));
* ```
*/
export function parse(text: string, options?: EJSON.Options): SerializableTypes;
export type JSONPrimitive = string | number | boolean | null;
export type SerializableTypes = Document | Array<JSONPrimitive | Document> | JSONPrimitive;
/**
* Converts a BSON document to an Extended JSON string, optionally replacing values if a replacer
* function is specified or optionally including only the specified properties if a replacer array
* is specified.
*
* @param value - The value to convert to extended JSON
* @param replacer - A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON string. If this value is null or not provided, all properties of the object are included in the resulting JSON string
* @param space - A String or Number object that's used to insert white space into the output JSON string for readability purposes.
* @param options - Optional settings
*
* @example
* ```js
* const { EJSON } = require('bson');
* const Int32 = require('mongodb').Int32;
* const doc = { int32: new Int32(10) };
*
* // prints '{"int32":{"$numberInt":"10"}}'
* console.log(EJSON.stringify(doc, { relaxed: false }));
*
* // prints '{"int32":10}'
* console.log(EJSON.stringify(doc));
* ```
*/
export function stringify(value: SerializableTypes, replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | EJSON.Options, space?: string | number, options?: EJSON.Options): string;
/**
* Serializes an object to an Extended JSON string, and reparse it as a JavaScript object.
*
* @param value - The object to serialize
* @param options - Optional settings passed to the `stringify` function
*/
export function serialize(value: SerializableTypes, options?: EJSON.Options): Document;
/**
* Deserializes an Extended JSON object into a plain JavaScript object with native/BSON types
*
* @param ejson - The Extended JSON object to deserialize
* @param options - Optional settings passed to the parse method
*/
export function deserialize(ejson: Document, options?: EJSON.Options): SerializableTypes;
}
declare function EJSONdeserialize(ejson: Document, options?: EJSONOptions): any;
/** @public */
export declare type EJSONOptions = EJSON.Options;
export declare type EJSONOptions = {
/** Output using the Extended JSON v1 spec */
legacy?: boolean;
/** Enable Extended JSON's `relaxed` mode, which attempts to return native JS types where possible, rather than BSON types */
relaxed?: boolean;
};
/**
* Serializes an object to an Extended JSON string, and reparse it as a JavaScript object.
*
* @param value - The object to serialize
* @param options - Optional settings passed to the `stringify` function
*/
declare function EJSONserialize(value: any, options?: EJSONOptions): Document;
/**
* A class representation of a BSON Int32 type.

@@ -591,3 +513,3 @@ * @public

export declare class Int32 {
_bsontype: 'Int32';
get _bsontype(): 'Int32';
value: number;

@@ -640,5 +562,5 @@ /**

export declare class Long {
_bsontype: 'Long';
get _bsontype(): 'Long';
/** An indicator used to reliably determine if an object is a Long or not. */
__isLong__: true;
get __isLong__(): boolean;
/**

@@ -943,3 +865,3 @@ * The high 32 bits as a signed value.

/** @public */
export declare type LongWithoutOverrides = new (low: unknown, high?: number, unsigned?: boolean) => {
export declare type LongWithoutOverrides = new (low: unknown, high?: number | boolean, unsigned?: boolean) => {
[P in Exclude<keyof Long, TimestampOverrides>]: Long[P];

@@ -951,6 +873,2 @@ };

/** @public */
declare let Map_2: MapConstructor;
export { Map_2 as Map }
/**

@@ -962,4 +880,3 @@ * A class representation of the BSON MaxKey type.

export declare class MaxKey {
_bsontype: 'MaxKey';
constructor();
get _bsontype(): 'MaxKey';
/* Excluded from this release type: toExtendedJSON */

@@ -981,4 +898,3 @@ /* Excluded from this release type: fromExtendedJSON */

export declare class MinKey {
_bsontype: 'MinKey';
constructor();
get _bsontype(): 'MinKey';
/* Excluded from this release type: toExtendedJSON */

@@ -999,4 +915,4 @@ /* Excluded from this release type: fromExtendedJSON */

*/
declare class ObjectId {
_bsontype: 'ObjectID';
export declare class ObjectId {
get _bsontype(): 'ObjectId';
/* Excluded from this release type: index */

@@ -1011,3 +927,3 @@ static cacheHexString: boolean;

*/
constructor(inputId?: string | number | ObjectId | ObjectIdLike | Buffer | Uint8Array);
constructor(inputId?: string | number | ObjectId | ObjectIdLike | Uint8Array);
/**

@@ -1017,10 +933,4 @@ * The ObjectId bytes

*/
get id(): Buffer;
set id(value: Buffer);
/**
* The generation time of this ObjectId instance
* @deprecated Please use getTimestamp / createFromTime which returns an int32 epoch
*/
get generationTime(): number;
set generationTime(value: number);
get id(): Uint8Array;
set id(value: Uint8Array);
/** Returns the ObjectId id as a 24 character hex string representation */

@@ -1034,9 +944,8 @@ toHexString(): string;

*/
static generate(time?: number): Buffer;
static generate(time?: number): Uint8Array;
/**
* Converts the id into a 24 character hex string for printing
*
* @param format - The Buffer toString format parameter.
* Converts the id into a 24 character hex string for printing, unless encoding is provided.
* @param encoding - hex or base64
*/
toString(format?: string): string;
toString(encoding?: 'hex' | 'base64'): string;
/** Converts to its JSON the 24 character hex string representation. */

@@ -1070,3 +979,3 @@ toJSON(): string;

*/
static isValid(id: string | number | ObjectId | ObjectIdLike | Buffer | Uint8Array): boolean;
static isValid(id: string | number | ObjectId | ObjectIdLike | Uint8Array): boolean;
/* Excluded from this release type: toExtendedJSON */

@@ -1076,4 +985,2 @@ /* Excluded from this release type: fromExtendedJSON */

}
export { ObjectId as ObjectID }
export { ObjectId }

@@ -1087,3 +994,3 @@ /** @public */

export declare interface ObjectIdLike {
id: string | Buffer;
id: string | Uint8Array;
__id?: string;

@@ -1094,2 +1001,20 @@ toHexString(): string;

/**
* Parse an Extended JSON string, constructing the JavaScript value or object described by that
* string.
*
* @example
* ```js
* const { EJSON } = require('bson');
* const text = '{ "int32": { "$numberInt": "10" } }';
*
* // prints { int32: { [String: '10'] _bsontype: 'Int32', value: '10' } }
* console.log(EJSON.parse(text, { relaxed: false }));
*
* // prints { int32: 10 }
* console.log(EJSON.parse(text));
* ```
*/
declare function parse(text: string, options?: EJSONOptions): any;
/**
* Serialize a Javascript object.

@@ -1101,3 +1026,3 @@ *

*/
export declare function serialize(object: Document, options?: SerializeOptions): Buffer;
export declare function serialize(object: Document, options?: SerializeOptions): Uint8Array;

@@ -1126,3 +1051,3 @@ /** @public */

*/
export declare function serializeWithBufferAndIndex(object: Document, finalBuffer: Buffer, options?: SerializeOptions): number;
export declare function serializeWithBufferAndIndex(object: Document, finalBuffer: Uint8Array, options?: SerializeOptions): number;

@@ -1138,2 +1063,27 @@ /**

/**
* Converts a BSON document to an Extended JSON string, optionally replacing values if a replacer
* function is specified or optionally including only the specified properties if a replacer array
* is specified.
*
* @param value - The value to convert to extended JSON
* @param replacer - A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON string. If this value is null or not provided, all properties of the object are included in the resulting JSON string
* @param space - A String or Number object that's used to insert white space into the output JSON string for readability purposes.
* @param options - Optional settings
*
* @example
* ```js
* const { EJSON } = require('bson');
* const Int32 = require('mongodb').Int32;
* const doc = { int32: new Int32(10) };
*
* // prints '{"int32":{"$numberInt":"10"}}'
* console.log(EJSON.stringify(doc, { relaxed: false }));
*
* // prints '{"int32":10}'
* console.log(EJSON.stringify(doc));
* ```
*/
declare function stringify(value: any, replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | EJSONOptions, space?: string | number, options?: EJSONOptions): string;
/**
* @public

@@ -1143,7 +1093,11 @@ * @category BSONType

export declare class Timestamp extends LongWithoutOverridesClass {
_bsontype: 'Timestamp';
get _bsontype(): 'Timestamp';
static readonly MAX_VALUE: Long;
/**
* @param low - A 64-bit Long representing the Timestamp.
* @param int - A 64-bit bigint representing the Timestamp.
*/
constructor(int: bigint);
/**
* @param long - A 64-bit Long representing the Timestamp.
*/
constructor(long: Long);

@@ -1157,8 +1111,2 @@ /**

});
/**
* @param low - the low (signed) 32 bits of the Timestamp.
* @param high - the high (signed) 32 bits of the Timestamp.
* @deprecated Please use `Timestamp({ t: high, i: low })` or `Timestamp(Long(low, high))` instead.
*/
constructor(low: number, high: number);
toJSON(): {

@@ -1213,3 +1161,3 @@ $timestamp: string;

*/
constructor(input?: string | Buffer | UUID);
constructor(input?: string | Uint8Array | UUID);
/**

@@ -1219,4 +1167,4 @@ * The UUID bytes

*/
get id(): Buffer;
set id(value: Buffer);
get id(): Uint8Array;
set id(value: Uint8Array);
/**

@@ -1230,3 +1178,3 @@ * Returns the UUID id as a 32 or 36 character hex string representation, excluding/including dashes (defaults to 36 character dash separated)

*/
toString(encoding?: string): string;
toString(encoding?: 'hex' | 'base64'): string;
/**

@@ -1242,3 +1190,3 @@ * Converts the id into its JSON string representation.

*/
equals(otherId: string | Buffer | UUID): boolean;
equals(otherId: string | Uint8Array | UUID): boolean;
/**

@@ -1251,3 +1199,3 @@ * Creates a Binary instance from the current UUID.

*/
static generate(): Buffer;
static generate(): Uint8Array;
/**

@@ -1257,3 +1205,3 @@ * Checks if a value is a valid bson UUID

*/
static isValid(input: string | Buffer | UUID): boolean;
static isValid(input: string | Uint8Array | UUID): boolean;
/**

@@ -1260,0 +1208,0 @@ * Creates an UUID from a hex string representation of an UUID.

@@ -12,9 +12,7 @@ {

"src",
"dist",
"bson.d.ts",
"etc/prepare.js",
"bower.json"
"etc/prepare.js"
],
"types": "bson.d.ts",
"version": "4.7.0",
"version": "5.0.0-alpha.0",
"author": {

@@ -31,46 +29,37 @@ "name": "The MongoDB NodeJS Team",

"devDependencies": {
"@babel/plugin-external-helpers": "^7.10.4",
"@babel/preset-env": "^7.11.0",
"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@microsoft/api-extractor": "^7.28.0",
"@rollup/plugin-babel": "^5.2.0",
"@rollup/plugin-commonjs": "^15.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^9.0.0",
"@rollup/plugin-replace": "^4.0.0",
"@rollup/plugin-typescript": "^6.0.0",
"@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.30.0",
"@typescript-eslint/parser": "^5.30.0",
"array-includes": "^3.1.3",
"array.prototype.flatmap": "^1.3.0",
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@microsoft/api-extractor": "^7.33.7",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-typescript": "^10.0.1",
"@types/chai": "^4.3.4",
"@types/mocha": "^10.0.1",
"@types/node": "^18.11.12",
"@types/sinon": "^10.0.13",
"@types/sinon-chai": "^3.2.9",
"@typescript-eslint/eslint-plugin": "^5.46.0",
"@typescript-eslint/parser": "^5.46.0",
"benchmark": "^2.1.4",
"chai": "^4.2.0",
"eslint": "^8.18.0",
"chai": "^4.3.7",
"chalk": "^5.1.2",
"eslint": "^8.29.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.1.0",
"eslint-plugin-tsdoc": "^0.2.16",
"karma": "^6.3.4",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^3.1.0",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-rollup-preprocessor": "^7.0.5",
"mocha": "5.2.0",
"node-fetch": "^2.6.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.17",
"magic-string": "^0.27.0",
"mocha": "10.1.0",
"node-fetch": "^3.2.10",
"nyc": "^15.1.0",
"object.entries": "^1.1.5",
"prettier": "^2.7.1",
"prettier": "^2.8.1",
"rimraf": "^3.0.2",
"rollup": "^2.26.5",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-node-polyfills": "^0.2.1",
"rollup-plugin-polyfill-node": "^0.7.0",
"rollup": "^3.7.1",
"sinon": "^15.0.0",
"sinon-chai": "^3.7.0",
"source-map-support": "^0.5.21",
"standard-version": "^9.5.0",
"ts-node": "^9.0.0",
"tsd": "^0.21.0",
"typescript": "^4.7.4",
"ts-node": "^10.9.1",
"tsd": "^0.25.0",
"typescript": "^4.9.4",
"typescript-cached-transpile": "0.0.6",
"uuid": "^8.3.2"
"uuid": "^9.0.0",
"v8-profiler-next": "^1.9.0"
},

@@ -89,31 +78,29 @@ "tsd": {

},
"main": "lib/bson.js",
"module": "dist/bson.esm.js",
"browser": {
"./lib/bson.js": "./dist/bson.browser.umd.js",
"./dist/bson.esm.js": "./dist/bson.browser.esm.js"
"main": "./lib/bson.cjs",
"module": "./lib/bson.mjs",
"browser": "./lib/bson.mjs",
"exports": {
"browser": "./lib/bson.mjs",
"import": "./lib/bson.mjs",
"require": "./lib/bson.cjs"
},
"engines": {
"node": ">=6.9.0"
"node": ">=14.20.1"
},
"scripts": {
"docs": "typedoc",
"test": "npm run build && npm run test-node && npm run test-browser",
"test-node": "mocha test/node test/*_tests.js",
"test-tsd": "npm run build:dts && tsd",
"test-browser": "node --max-old-space-size=4096 ./node_modules/.bin/karma start karma.conf.js",
"build:ts": "tsc",
"build:dts": "npm run build:ts && api-extractor run --typescript-compiler-folder node_modules/typescript --local && rimraf 'lib/**/*.d.ts*'",
"build:bundle": "rollup -c rollup.config.js",
"pretest": "npm run build",
"test": "npm run check:node && npm run check:web",
"check:node": "WEB=false mocha test/node",
"check:tsd": "npm run build:dts && tsd",
"check:web": "WEB=true mocha test/node",
"build:ts": "node ./node_modules/typescript/bin/tsc",
"build:dts": "npm run build:ts && api-extractor run --typescript-compiler-folder node_modules/typescript --local && rimraf 'lib/**/*.d.ts*' lib/parser lib/utils",
"build:bundle": "rollup -c rollup.config.mjs",
"build": "npm run build:dts && npm run build:bundle",
"lint": "eslint -v && eslint --ext '.js,.ts' --max-warnings=0 src test && tsc -v && tsc --noEmit && npm run test-tsd",
"check:lint": "eslint -v && eslint --ext '.js,.ts' --max-warnings=0 src test && npm run build:dts && npm run check:tsd",
"format": "eslint --ext '.js,.ts' src test --fix",
"coverage": "nyc npm run test-node",
"coverage:html": "npm run coverage && open ./coverage/index.html",
"check:coverage": "nyc --check-coverage npm run check:node",
"prepare": "node etc/prepare.js",
"release": "standard-version -i HISTORY.md"
},
"dependencies": {
"buffer": "^5.6.0"
}
}

@@ -1,11 +0,10 @@

import { Buffer } from 'buffer';
import { ensureBuffer } from './ensure_buffer';
import { bufferToUuidHexString, uuidHexStringToBuffer, uuidValidateString } from './uuid_utils';
import { isUint8Array, randomBytes } from './parser/utils';
import { isUint8Array } from './parser/utils';
import type { EJSONOptions } from './extended_json';
import { BSONError, BSONTypeError } from './error';
import { BSON_BINARY_SUBTYPE_UUID_NEW } from './constants';
import { ByteUtils } from './utils/byte_utils';
/** @public */
export type BinarySequence = Uint8Array | Buffer | number[];
export type BinarySequence = Uint8Array | number[];

@@ -32,3 +31,9 @@ /** @public */

export class Binary {
_bsontype!: 'Binary';
get _bsontype(): 'Binary' {
return 'Binary';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -62,3 +67,3 @@ /**

buffer!: Buffer;
buffer!: Uint8Array;
sub_type!: number;

@@ -79,4 +84,2 @@ position!: number;

constructor(buffer?: string | BinarySequence, subType?: number) {
if (!(this instanceof Binary)) return new Binary(buffer, subType);
if (

@@ -98,3 +101,3 @@ !(buffer == null) &&

// create an empty binary buffer
this.buffer = Buffer.alloc(Binary.BUFFER_SIZE);
this.buffer = ByteUtils.allocate(Binary.BUFFER_SIZE);
this.position = 0;

@@ -104,9 +107,9 @@ } else {

// string
this.buffer = Buffer.from(buffer, 'binary');
this.buffer = ByteUtils.fromISO88591(buffer);
} else if (Array.isArray(buffer)) {
// number[]
this.buffer = Buffer.from(buffer);
this.buffer = ByteUtils.fromNumberArray(buffer);
} else {
// Buffer | TypedArray | ArrayBuffer
this.buffer = ensureBuffer(buffer);
this.buffer = ByteUtils.toLocalBufferType(buffer);
}

@@ -123,3 +126,3 @@

*/
put(byteValue: string | number | Uint8Array | Buffer | number[]): void {
put(byteValue: string | number | Uint8Array | number[]): void {
// If it's a string and a has more than one character throw an error

@@ -145,9 +148,8 @@ if (typeof byteValue === 'string' && byteValue.length !== 1) {

if (this.buffer.length > this.position) {
if (this.buffer.byteLength > this.position) {
this.buffer[this.position++] = decodedByte;
} else {
const buffer = Buffer.alloc(Binary.BUFFER_SIZE + this.buffer.length);
// Combine the two buffers together
this.buffer.copy(buffer, 0, 0, this.buffer.length);
this.buffer = buffer;
const newSpace = ByteUtils.allocate(Binary.BUFFER_SIZE + this.buffer.length);
newSpace.set(this.buffer, 0);
this.buffer = newSpace;
this.buffer[this.position++] = decodedByte;

@@ -167,16 +169,17 @@ }

// If the buffer is to small let's extend the buffer
if (this.buffer.length < offset + sequence.length) {
const buffer = Buffer.alloc(this.buffer.length + sequence.length);
this.buffer.copy(buffer, 0, 0, this.buffer.length);
if (this.buffer.byteLength < offset + sequence.length) {
const newSpace = ByteUtils.allocate(this.buffer.byteLength + sequence.length);
newSpace.set(this.buffer, 0);
// Assign the new buffer
this.buffer = buffer;
this.buffer = newSpace;
}
if (ArrayBuffer.isView(sequence)) {
this.buffer.set(ensureBuffer(sequence), offset);
this.buffer.set(ByteUtils.toLocalBufferType(sequence), offset);
this.position =
offset + sequence.byteLength > this.position ? offset + sequence.length : this.position;
} else if (typeof sequence === 'string') {
this.buffer.write(sequence, offset, sequence.length, 'binary');
const bytes = ByteUtils.fromISO88591(sequence);
this.buffer.set(bytes, offset);
this.position =

@@ -218,3 +221,4 @@ offset + sequence.length > this.position ? offset + sequence.length : this.position;

}
return this.buffer.toString('binary', 0, this.position);
// TODO(NODE-4361): remove binary string support, value(true) should be the default / only option here.
return ByteUtils.toISO88591(this.buffer.subarray(0, this.position));
}

@@ -228,7 +232,10 @@

toJSON(): string {
return this.buffer.toString('base64');
return ByteUtils.toBase64(this.buffer);
}
toString(format?: string): string {
return this.buffer.toString(format);
toString(encoding?: 'hex' | 'base64' | 'utf8' | 'utf-8'): string {
if (encoding === 'hex') return ByteUtils.toHex(this.buffer);
if (encoding === 'base64') return ByteUtils.toBase64(this.buffer);
if (encoding === 'utf8' || encoding === 'utf-8') return ByteUtils.toUTF8(this.buffer);
return ByteUtils.toUTF8(this.buffer);
}

@@ -239,3 +246,3 @@

options = options || {};
const base64String = this.buffer.toString('base64');
const base64String = ByteUtils.toBase64(this.buffer);

@@ -273,3 +280,3 @@ const subType = Number(this.sub_type).toString(16);

options = options || {};
let data: Buffer | undefined;
let data: Uint8Array | undefined;
let type;

@@ -279,7 +286,7 @@ if ('$binary' in doc) {

type = doc.$type ? parseInt(doc.$type, 16) : 0;
data = Buffer.from(doc.$binary, 'base64');
data = ByteUtils.fromBase64(doc.$binary);
} else {
if (typeof doc.$binary !== 'string') {
type = doc.$binary.subType ? parseInt(doc.$binary.subType, 16) : 0;
data = Buffer.from(doc.$binary.base64, 'base64');
data = ByteUtils.fromBase64(doc.$binary.base64);
}

@@ -303,9 +310,6 @@ }

inspect(): string {
const asBuffer = this.value(true);
return `new Binary(Buffer.from("${asBuffer.toString('hex')}", "hex"), ${this.sub_type})`;
return `new Binary(Buffer.from("${ByteUtils.toHex(this.buffer)}", "hex"), ${this.sub_type})`;
}
}
Object.defineProperty(Binary.prototype, '_bsontype', { value: 'Binary' });
/** @public */

@@ -322,2 +326,7 @@ export type UUIDExtended = {

export class UUID extends Binary {
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}
static cacheHexString: boolean;

@@ -333,4 +342,4 @@

*/
constructor(input?: string | Buffer | UUID) {
let bytes;
constructor(input?: string | Uint8Array | UUID) {
let bytes: Uint8Array;
let hexStr;

@@ -340,6 +349,6 @@ if (input == null) {

} else if (input instanceof UUID) {
bytes = Buffer.from(input.buffer);
bytes = ByteUtils.toLocalBufferType(new Uint8Array(input.buffer));
hexStr = input.__id;
} else if (ArrayBuffer.isView(input) && input.byteLength === UUID_BYTE_LENGTH) {
bytes = ensureBuffer(input);
bytes = ByteUtils.toLocalBufferType(input);
} else if (typeof input === 'string') {

@@ -360,7 +369,7 @@ bytes = uuidHexStringToBuffer(input);

*/
get id(): Buffer {
get id(): Uint8Array {
return this.buffer;
}
set id(value: Buffer) {
set id(value: Uint8Array) {
this.buffer = value;

@@ -394,4 +403,6 @@

*/
toString(encoding?: string): string {
return encoding ? this.id.toString(encoding) : this.toHexString();
toString(encoding?: 'hex' | 'base64'): string {
if (encoding === 'hex') return ByteUtils.toHex(this.id);
if (encoding === 'base64') return ByteUtils.toBase64(this.id);
return this.toHexString();
}

@@ -412,3 +423,3 @@

*/
equals(otherId: string | Buffer | UUID): boolean {
equals(otherId: string | Uint8Array | UUID): boolean {
if (!otherId) {

@@ -419,7 +430,7 @@ return false;

if (otherId instanceof UUID) {
return otherId.id.equals(this.id);
return ByteUtils.equals(otherId.id, this.id);
}
try {
return new UUID(otherId).id.equals(this.id);
return ByteUtils.equals(new UUID(otherId).id, this.id);
} catch {

@@ -440,4 +451,4 @@ return false;

*/
static generate(): Buffer {
const bytes = randomBytes(UUID_BYTE_LENGTH);
static generate(): Uint8Array {
const bytes = ByteUtils.randomBytes(UUID_BYTE_LENGTH);

@@ -449,3 +460,3 @@ // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`

return Buffer.from(bytes);
return bytes;
}

@@ -457,3 +468,3 @@

*/
static isValid(input: string | Buffer | UUID): boolean {
static isValid(input: string | Uint8Array | UUID): boolean {
if (!input) {

@@ -473,3 +484,3 @@ return false;

// check for length & uuid version (https://tools.ietf.org/html/rfc4122#section-4.1.3)
if (input.length !== UUID_BYTE_LENGTH) {
if (input.byteLength !== UUID_BYTE_LENGTH) {
return false;

@@ -476,0 +487,0 @@ }

@@ -1,2 +0,1 @@

import { Buffer } from 'buffer';
import { Binary, UUID } from './binary';

@@ -7,56 +6,17 @@ import { Code } from './code';

import { Double } from './double';
import { ensureBuffer } from './ensure_buffer';
import { EJSON } from './extended_json';
import { Int32 } from './int_32';
import { Long } from './long';
import { Map } from './map';
import { MaxKey } from './max_key';
import { MinKey } from './min_key';
import { ObjectId } from './objectid';
import { BSONError, BSONTypeError } from './error';
import { calculateObjectSize as internalCalculateObjectSize } from './parser/calculate_size';
import { internalCalculateObjectSize } from './parser/calculate_size';
// Parts of the parser
import { deserialize as internalDeserialize, DeserializeOptions } from './parser/deserializer';
import { serializeInto as internalSerialize, SerializeOptions } from './parser/serializer';
import { internalDeserialize, DeserializeOptions } from './parser/deserializer';
import { serializeInto, SerializeOptions } from './parser/serializer';
import { BSONRegExp } from './regexp';
import { BSONSymbol } from './symbol';
import { Timestamp } from './timestamp';
import { ByteUtils } from './utils/byte_utils';
export type { UUIDExtended, BinaryExtended, BinaryExtendedLegacy, BinarySequence } from './binary';
export type { CodeExtended } from './code';
export {
BSON_BINARY_SUBTYPE_BYTE_ARRAY,
BSON_BINARY_SUBTYPE_DEFAULT,
BSON_BINARY_SUBTYPE_FUNCTION,
BSON_BINARY_SUBTYPE_MD5,
BSON_BINARY_SUBTYPE_USER_DEFINED,
BSON_BINARY_SUBTYPE_UUID,
BSON_BINARY_SUBTYPE_UUID_NEW,
BSON_BINARY_SUBTYPE_ENCRYPTED,
BSON_BINARY_SUBTYPE_COLUMN,
BSON_DATA_ARRAY,
BSON_DATA_BINARY,
BSON_DATA_BOOLEAN,
BSON_DATA_CODE,
BSON_DATA_CODE_W_SCOPE,
BSON_DATA_DATE,
BSON_DATA_DBPOINTER,
BSON_DATA_DECIMAL128,
BSON_DATA_INT,
BSON_DATA_LONG,
BSON_DATA_MAX_KEY,
BSON_DATA_MIN_KEY,
BSON_DATA_NULL,
BSON_DATA_NUMBER,
BSON_DATA_OBJECT,
BSON_DATA_OID,
BSON_DATA_REGEXP,
BSON_DATA_STRING,
BSON_DATA_SYMBOL,
BSON_DATA_TIMESTAMP,
BSON_DATA_UNDEFINED,
BSON_INT32_MAX,
BSON_INT32_MIN,
BSON_INT64_MAX,
BSON_INT64_MIN
} from './constants';
export type { DBRefLike } from './db_ref';

@@ -66,3 +26,2 @@ export type { Decimal128Extended } from './decimal128';

export type { EJSONOptions } from './extended_json';
export { EJSON } from './extended_json';
export type { Int32Extended } from './int_32';

@@ -76,7 +35,7 @@ export type { LongExtended } from './long';

export type { LongWithoutOverrides, TimestampExtended, TimestampOverrides } from './timestamp';
export { LongWithoutOverridesClass } from './timestamp';
export type { LongWithoutOverridesClass } from './timestamp';
export type { SerializeOptions, DeserializeOptions };
export {
Code,
Map,
BSONSymbol,

@@ -94,9 +53,7 @@ DBRef,

BSONRegExp,
Decimal128,
// In 4.0.0 and 4.0.1, this property name was changed to ObjectId to match the class name.
// This caused interoperability problems with previous versions of the library, so in
// later builds we changed it back to ObjectID (capital D) to match legacy implementations.
ObjectId as ObjectID
Decimal128
};
export { BSONError, BSONTypeError } from './error';
export { BSONType } from './constants';
export { EJSON } from './extended_json';

@@ -114,3 +71,3 @@ /** @public */

// Current Internal Temporary Serialization Buffer
let buffer = Buffer.alloc(MAXSIZE);
let buffer = ByteUtils.allocate(MAXSIZE);

@@ -126,3 +83,3 @@ /**

if (buffer.length < size) {
buffer = Buffer.alloc(size);
buffer = ByteUtils.allocate(size);
}

@@ -138,3 +95,3 @@ }

*/
export function serialize(object: Document, options: SerializeOptions = {}): Buffer {
export function serialize(object: Document, options: SerializeOptions = {}): Uint8Array {
// Unpack the options

@@ -151,7 +108,7 @@ const checkKeys = typeof options.checkKeys === 'boolean' ? options.checkKeys : false;

if (buffer.length < minInternalBufferSize) {
buffer = Buffer.alloc(minInternalBufferSize);
buffer = ByteUtils.allocate(minInternalBufferSize);
}
// Attempt to serialize
const serializationIndex = internalSerialize(
const serializationIndex = serializeInto(
buffer,

@@ -164,10 +121,10 @@ object,

ignoreUndefined,
[]
null
);
// Create the final buffer
const finishedBuffer = Buffer.alloc(serializationIndex);
const finishedBuffer = ByteUtils.allocate(serializationIndex);
// Copy into the finished buffer
buffer.copy(finishedBuffer, 0, 0, finishedBuffer.length);
finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);

@@ -189,3 +146,3 @@ // Return the buffer

object: Document,
finalBuffer: Buffer,
finalBuffer: Uint8Array,
options: SerializeOptions = {}

@@ -202,3 +159,3 @@ ): number {

// Attempt to serialize
const serializationIndex = internalSerialize(
const serializationIndex = serializeInto(
buffer,

@@ -210,6 +167,8 @@ object,

serializeFunctions,
ignoreUndefined
ignoreUndefined,
null
);
buffer.copy(finalBuffer, startIndex, 0, serializationIndex);
finalBuffer.set(buffer.subarray(0, serializationIndex), startIndex);
// Return the index

@@ -226,7 +185,4 @@ return startIndex + serializationIndex - 1;

*/
export function deserialize(
buffer: Buffer | ArrayBufferView | ArrayBuffer,
options: DeserializeOptions = {}
): Document {
return internalDeserialize(buffer instanceof Buffer ? buffer : ensureBuffer(buffer), options);
export function deserialize(buffer: Uint8Array, options: DeserializeOptions = {}): Document {
return internalDeserialize(ByteUtils.toLocalBufferType(buffer), options);
}

@@ -274,3 +230,3 @@

export function deserializeStream(
data: Buffer | ArrayBufferView | ArrayBuffer,
data: Uint8Array | ArrayBuffer,
startIndex: number,

@@ -286,3 +242,3 @@ numberOfDocuments: number,

);
const bufferData = ensureBuffer(data);
const bufferData = ByteUtils.toLocalBufferType(data);

@@ -309,38 +265,1 @@ let index = startIndex;

}
/**
* BSON default export
* @deprecated Please use named exports
* @privateRemarks
* We want to someday deprecate the default export,
* so none of the new TS types are being exported on the default
* @public
*/
const BSON = {
Binary,
Code,
DBRef,
Decimal128,
Double,
Int32,
Long,
UUID,
Map,
MaxKey,
MinKey,
ObjectId,
ObjectID: ObjectId,
BSONRegExp,
BSONSymbol,
Timestamp,
EJSON,
setInternalBufferSize,
serialize,
serializeWithBufferAndIndex,
deserialize,
calculateObjectSize,
deserializeStream,
BSONError,
BSONTypeError
};
export default BSON;

@@ -5,3 +5,3 @@ import type { Document } from './bson';

export interface CodeExtended {
$code: string | Function;
$code: string;
$scope?: Document;

@@ -16,6 +16,16 @@ }

export class Code {
_bsontype!: 'Code';
get _bsontype(): 'Code' {
return 'Code';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}
code!: string | Function;
scope?: Document;
code: string;
// a code instance having a null scope is what determines whether
// it is BSONType 0x0D (just code) / 0x0F (code with scope)
scope: Document | null;
/**

@@ -25,11 +35,13 @@ * @param code - a string or function.

*/
constructor(code: string | Function, scope?: Document) {
if (!(this instanceof Code)) return new Code(code, scope);
this.code = code;
this.scope = scope;
constructor(code: string | Function, scope?: Document | null) {
this.code = code.toString();
this.scope = scope ?? null;
}
toJSON(): { code: string | Function; scope?: Document } {
return { code: this.code, scope: this.scope };
toJSON(): { code: string; scope?: Document } {
if (this.scope != null) {
return { code: this.code, scope: this.scope };
}
return { code: this.code };
}

@@ -59,7 +71,5 @@

return `new Code("${String(codeJson.code)}"${
codeJson.scope ? `, ${JSON.stringify(codeJson.scope)}` : ''
codeJson.scope != null ? `, ${JSON.stringify(codeJson.scope)}` : ''
})`;
}
}
Object.defineProperty(Code.prototype, '_bsontype', { value: 'Code' });

@@ -111,1 +111,29 @@ /** @internal */

export const BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
/** @public */
export const BSONType = Object.freeze({
double: 1,
string: 2,
object: 3,
array: 4,
binData: 5,
undefined: 6,
objectId: 7,
bool: 8,
date: 9,
null: 10,
regex: 11,
dbPointer: 12,
javascript: 13,
symbol: 14,
javascriptWithScope: 15,
int: 16,
timestamp: 17,
long: 18,
decimal: 19,
minKey: -1,
maxKey: 127
} as const);
/** @public */
export type BSONType = typeof BSONType[keyof typeof BSONType];
import type { Document } from './bson';
import type { EJSONOptions } from './extended_json';
import type { ObjectId } from './objectid';
import { isObjectLike } from './parser/utils';

@@ -16,6 +15,10 @@ /** @public */

return (
isObjectLike(value) &&
value != null &&
typeof value === 'object' &&
'$id' in value &&
value.$id != null &&
'$ref' in value &&
typeof value.$ref === 'string' &&
(value.$db == null || typeof value.$db === 'string')
// If '$db' is defined it MUST be a string, otherwise it should be absent
(!('$db' in value) || ('$db' in value && typeof value.$db === 'string'))
);

@@ -30,3 +33,9 @@ }

export class DBRef {
_bsontype!: 'DBRef';
get _bsontype(): 'DBRef' {
return 'DBRef';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -44,4 +53,2 @@ collection!: string;

constructor(collection: string, oid: ObjectId, db?: string, fields?: Document) {
if (!(this instanceof DBRef)) return new DBRef(collection, oid, db, fields);
// check if namespace has been provided

@@ -126,3 +133,1 @@ const parts = collection.split('.');

}
Object.defineProperty(DBRef.prototype, '_bsontype', { value: 'DBRef' });

@@ -1,5 +0,5 @@

import { Buffer } from 'buffer';
import { BSONTypeError } from './error';
import { Long } from './long';
import { isUint8Array } from './parser/utils';
import { ByteUtils } from './utils/byte_utils';

@@ -16,12 +16,18 @@ const PARSE_STRING_REGEXP = /^(\+|-)?(\d+|(\d*\.\d*))?(E|e)?([-+])?(\d+)?$/;

// Nan value bits as 32 bit values (due to lack of longs)
const NAN_BUFFER = [
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
].reverse();
const NAN_BUFFER = ByteUtils.fromNumberArray(
[
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
].reverse()
);
// Infinity value bits 32 bit values (due to lack of longs)
const INF_NEGATIVE_BUFFER = [
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
].reverse();
const INF_POSITIVE_BUFFER = [
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
].reverse();
const INF_NEGATIVE_BUFFER = ByteUtils.fromNumberArray(
[
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
].reverse()
);
const INF_POSITIVE_BUFFER = ByteUtils.fromNumberArray(
[
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
].reverse()
);

@@ -125,5 +131,11 @@ const EXPONENT_REGEX = /^([-+])?(\d+)?$/;

export class Decimal128 {
_bsontype!: 'Decimal128';
get _bsontype(): 'Decimal128' {
return 'Decimal128';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}
readonly bytes!: Buffer;
readonly bytes!: Uint8Array;

@@ -134,5 +146,3 @@ /**

*/
constructor(bytes: Buffer | string) {
if (!(this instanceof Decimal128)) return new Decimal128(bytes);
constructor(bytes: Uint8Array | string) {
if (typeof bytes === 'string') {

@@ -245,5 +255,5 @@ this.bytes = Decimal128.fromString(bytes).bytes;

if (representation[index] === 'i' || representation[index] === 'I') {
return new Decimal128(Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER));
return new Decimal128(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER);
} else if (representation[index] === 'N') {
return new Decimal128(Buffer.from(NAN_BUFFER));
return new Decimal128(NAN_BUFFER);
}

@@ -292,3 +302,3 @@ }

// No digits read
if (!match || !match[2]) return new Decimal128(Buffer.from(NAN_BUFFER));
if (!match || !match[2]) return new Decimal128(NAN_BUFFER);

@@ -303,3 +313,3 @@ // Get exponent

// Return not a number
if (representation[index]) return new Decimal128(Buffer.from(NAN_BUFFER));
if (representation[index]) return new Decimal128(NAN_BUFFER);

@@ -432,5 +442,3 @@ // Done reading input

} else {
return new Decimal128(
Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER)
);
return new Decimal128(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER);
}

@@ -513,3 +521,3 @@ }

// Encode into a buffer
const buffer = Buffer.alloc(16);
const buffer = ByteUtils.allocate(16);
index = 0;

@@ -780,3 +788,1 @@

}
Object.defineProperty(Decimal128.prototype, '_bsontype', { value: 'Decimal128' });

@@ -14,3 +14,9 @@ import type { EJSONOptions } from './extended_json';

export class Double {
_bsontype!: 'Double';
get _bsontype(): 'Double' {
return 'Double';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -24,4 +30,2 @@ value!: number;

constructor(value: number) {
if (!(this instanceof Double)) return new Double(value);
if ((value as unknown) instanceof Number) {

@@ -92,3 +96,1 @@ value = value.valueOf();

}
Object.defineProperty(Double.prototype, '_bsontype', { value: 'Double' });

@@ -5,3 +5,2 @@ /** @public */

super(message);
Object.setPrototypeOf(this, BSONError.prototype);
}

@@ -18,3 +17,2 @@

super(message);
Object.setPrototypeOf(this, BSONTypeError.prototype);
}

@@ -21,0 +19,0 @@

import { Binary } from './binary';
import type { Document } from './bson';
import { Code } from './code';
import { BSON_INT32_MAX, BSON_INT32_MIN, BSON_INT64_MAX, BSON_INT64_MIN } from './constants';
import { DBRef, isDBRefLike } from './db_ref';

@@ -13,3 +14,3 @@ import { Decimal128 } from './decimal128';

import { ObjectId } from './objectid';
import { isDate, isObjectLike, isRegExp } from './parser/utils';
import { isDate, isRegExp } from './parser/utils';
import { BSONRegExp } from './regexp';

@@ -20,3 +21,8 @@ import { BSONSymbol } from './symbol';

/** @public */
export type EJSONOptions = EJSON.Options;
export type EJSONOptions = {
/** Output using the Extended JSON v1 spec */
legacy?: boolean;
/** Enable Extended JSON's `relaxed` mode, which attempts to return native JS types where possible, rather than BSON types */
relaxed?: boolean;
};

@@ -39,16 +45,11 @@ /** @internal */

export function isBSONType(value: unknown): value is BSONType {
function isBSONType(value: unknown): value is BSONType {
return (
isObjectLike(value) && Reflect.has(value, '_bsontype') && typeof value._bsontype === 'string'
value != null &&
typeof value === 'object' &&
'_bsontype' in value &&
typeof value._bsontype === 'string'
);
}
// INT32 boundaries
const BSON_INT32_MAX = 0x7fffffff;
const BSON_INT32_MIN = -0x80000000;
// INT64 boundaries
// const BSON_INT64_MAX = 0x7fffffffffffffff; // TODO(NODE-4377): This number cannot be precisely represented in JS
const BSON_INT64_MAX = 0x8000000000000000;
const BSON_INT64_MIN = -0x8000000000000000;
// all the types where we don't need to do any special processing and can just pass the EJSON

@@ -73,3 +74,3 @@ //straight to type.fromExtendedJSON

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function deserializeValue(value: any, options: EJSON.Options = {}) {
function deserializeValue(value: any, options: EJSONOptions = {}) {
if (typeof value === 'number') {

@@ -80,7 +81,11 @@ if (options.relaxed || options.legacy) {

// if it's an integer, should interpret as smallest BSON integer
// that can represent it exactly. (if out of range, interpret as double.)
if (Math.floor(value) === value) {
if (value >= BSON_INT32_MIN && value <= BSON_INT32_MAX) return new Int32(value);
if (value >= BSON_INT64_MIN && value <= BSON_INT64_MAX) return Long.fromNumber(value);
if (Number.isInteger(value) && !Object.is(value, -0)) {
// interpret as being of the smallest BSON integer type that can represent the number exactly
if (value >= BSON_INT32_MIN && value <= BSON_INT32_MAX) {
return new Int32(value);
}
if (value >= BSON_INT64_MIN && value <= BSON_INT64_MAX) {
// TODO(NODE-4377): EJSON js number handling diverges from BSON
return Long.fromNumber(value);
}
}

@@ -150,3 +155,3 @@

type EJSONSerializeOptions = EJSON.Options & {
type EJSONSerializeOptions = EJSONOptions & {
seenObjects: { obj: unknown; propertyName: string }[];

@@ -225,12 +230,13 @@ };

if (typeof value === 'number' && (!options.relaxed || !isFinite(value))) {
// it's an integer
if (Math.floor(value) === value) {
const int32Range = value >= BSON_INT32_MIN && value <= BSON_INT32_MAX,
int64Range = value >= BSON_INT64_MIN && value <= BSON_INT64_MAX;
if (Number.isInteger(value) && !Object.is(value, -0)) {
// interpret as being of the smallest BSON integer type that can represent the number exactly
if (int32Range) return { $numberInt: value.toString() };
if (int64Range) return { $numberLong: value.toString() };
if (value >= BSON_INT32_MIN && value <= BSON_INT32_MAX) {
return { $numberInt: value.toString() };
}
if (value >= BSON_INT64_MIN && value <= BSON_INT64_MAX) {
// TODO(NODE-4377): EJSON js number handling diverges from BSON
return { $numberLong: value.toString() };
}
}
return { $numberDouble: value.toString() };
return { $numberDouble: Object.is(value, -0) ? '-0.0' : value.toString() };
}

@@ -277,6 +283,5 @@

MinKey: () => new MinKey(),
ObjectID: (o: ObjectId) => new ObjectId(o),
ObjectId: (o: ObjectId) => new ObjectId(o), // support 4.0.0/4.0.1 before _bsontype was reverted back to ObjectID
ObjectId: (o: ObjectId) => new ObjectId(o),
BSONRegExp: (o: BSONRegExp) => new BSONRegExp(o.pattern, o.options),
Symbol: (o: BSONSymbol) => new BSONSymbol(o.value),
BSONSymbol: (o: BSONSymbol) => new BSONSymbol(o.value),
Timestamp: (o: Timestamp) => Timestamp.fromBits(o.low, o.high)

@@ -293,3 +298,3 @@ } as const;

const _doc: Document = {};
for (const name in doc) {
for (const name of Object.keys(doc)) {
options.seenObjects.push({ propertyName: name, obj: null });

@@ -313,2 +318,9 @@ try {

return _doc;
} else if (
doc != null &&
typeof doc === 'object' &&
typeof doc._bsontype === 'string' &&
doc[Symbol.for('@@mdb.bson.version')] == null
) {
throw new BSONError('Unsupported BSON version, bson types must be from bson 5.0 or later');
} else if (isBSONType(doc)) {

@@ -349,125 +361,113 @@ // the "document" is really just a BSON type object

/**
* EJSON parse / stringify API
* @public
* Parse an Extended JSON string, constructing the JavaScript value or object described by that
* string.
*
* @example
* ```js
* const { EJSON } = require('bson');
* const text = '{ "int32": { "$numberInt": "10" } }';
*
* // prints { int32: { [String: '10'] _bsontype: 'Int32', value: '10' } }
* console.log(EJSON.parse(text, { relaxed: false }));
*
* // prints { int32: 10 }
* console.log(EJSON.parse(text));
* ```
*/
// the namespace here is used to emulate `export * as EJSON from '...'`
// which as of now (sept 2020) api-extractor does not support
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace EJSON {
export interface Options {
/** Output using the Extended JSON v1 spec */
legacy?: boolean;
/** Enable Extended JSON's `relaxed` mode, which attempts to return native JS types where possible, rather than BSON types */
relaxed?: boolean;
/**
* Disable Extended JSON's `relaxed` mode, which attempts to return BSON types where possible, rather than native JS types
* @deprecated Please use the relaxed property instead
*/
strict?: boolean;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function parse(text: string, options?: EJSONOptions): any {
return JSON.parse(text, (key, value) => {
if (key.indexOf('\x00') !== -1) {
throw new BSONError(
`BSON Document field names cannot contain null bytes, found: ${JSON.stringify(key)}`
);
}
return deserializeValue(value, { relaxed: true, legacy: false, ...options });
});
}
/**
* Parse an Extended JSON string, constructing the JavaScript value or object described by that
* string.
*
* @example
* ```js
* const { EJSON } = require('bson');
* const text = '{ "int32": { "$numberInt": "10" } }';
*
* // prints { int32: { [String: '10'] _bsontype: 'Int32', value: '10' } }
* console.log(EJSON.parse(text, { relaxed: false }));
*
* // prints { int32: 10 }
* console.log(EJSON.parse(text));
* ```
*/
export function parse(text: string, options?: EJSON.Options): SerializableTypes {
const finalOptions = Object.assign({}, { relaxed: true, legacy: false }, options);
// relaxed implies not strict
if (typeof finalOptions.relaxed === 'boolean') finalOptions.strict = !finalOptions.relaxed;
if (typeof finalOptions.strict === 'boolean') finalOptions.relaxed = !finalOptions.strict;
return JSON.parse(text, (key, value) => {
if (key.indexOf('\x00') !== -1) {
throw new BSONError(
`BSON Document field names cannot contain null bytes, found: ${JSON.stringify(key)}`
);
}
return deserializeValue(value, finalOptions);
});
/**
* Converts a BSON document to an Extended JSON string, optionally replacing values if a replacer
* function is specified or optionally including only the specified properties if a replacer array
* is specified.
*
* @param value - The value to convert to extended JSON
* @param replacer - A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON string. If this value is null or not provided, all properties of the object are included in the resulting JSON string
* @param space - A String or Number object that's used to insert white space into the output JSON string for readability purposes.
* @param options - Optional settings
*
* @example
* ```js
* const { EJSON } = require('bson');
* const Int32 = require('mongodb').Int32;
* const doc = { int32: new Int32(10) };
*
* // prints '{"int32":{"$numberInt":"10"}}'
* console.log(EJSON.stringify(doc, { relaxed: false }));
*
* // prints '{"int32":10}'
* console.log(EJSON.stringify(doc));
* ```
*/
function stringify(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | EJSONOptions,
space?: string | number,
options?: EJSONOptions
): string {
if (space != null && typeof space === 'object') {
options = space;
space = 0;
}
if (replacer != null && typeof replacer === 'object' && !Array.isArray(replacer)) {
options = replacer;
replacer = undefined;
space = 0;
}
const serializeOptions = Object.assign({ relaxed: true, legacy: false }, options, {
seenObjects: [{ propertyName: '(root)', obj: null }]
});
export type JSONPrimitive = string | number | boolean | null;
export type SerializableTypes = Document | Array<JSONPrimitive | Document> | JSONPrimitive;
const doc = serializeValue(value, serializeOptions);
return JSON.stringify(doc, replacer as Parameters<JSON['stringify']>[1], space);
}
/**
* Converts a BSON document to an Extended JSON string, optionally replacing values if a replacer
* function is specified or optionally including only the specified properties if a replacer array
* is specified.
*
* @param value - The value to convert to extended JSON
* @param replacer - A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON string. If this value is null or not provided, all properties of the object are included in the resulting JSON string
* @param space - A String or Number object that's used to insert white space into the output JSON string for readability purposes.
* @param options - Optional settings
*
* @example
* ```js
* const { EJSON } = require('bson');
* const Int32 = require('mongodb').Int32;
* const doc = { int32: new Int32(10) };
*
* // prints '{"int32":{"$numberInt":"10"}}'
* console.log(EJSON.stringify(doc, { relaxed: false }));
*
* // prints '{"int32":10}'
* console.log(EJSON.stringify(doc));
* ```
*/
export function stringify(
value: SerializableTypes,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | EJSON.Options,
space?: string | number,
options?: EJSON.Options
): string {
if (space != null && typeof space === 'object') {
options = space;
space = 0;
}
if (replacer != null && typeof replacer === 'object' && !Array.isArray(replacer)) {
options = replacer;
replacer = undefined;
space = 0;
}
const serializeOptions = Object.assign({ relaxed: true, legacy: false }, options, {
seenObjects: [{ propertyName: '(root)', obj: null }]
});
/**
* Serializes an object to an Extended JSON string, and reparse it as a JavaScript object.
*
* @param value - The object to serialize
* @param options - Optional settings passed to the `stringify` function
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function EJSONserialize(value: any, options?: EJSONOptions): Document {
options = options || {};
return JSON.parse(stringify(value, options));
}
const doc = serializeValue(value, serializeOptions);
return JSON.stringify(doc, replacer as Parameters<JSON['stringify']>[1], space);
}
/**
* Deserializes an Extended JSON object into a plain JavaScript object with native/BSON types
*
* @param ejson - The Extended JSON object to deserialize
* @param options - Optional settings passed to the parse method
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function EJSONdeserialize(ejson: Document, options?: EJSONOptions): any {
options = options || {};
return parse(JSON.stringify(ejson), options);
}
/**
* Serializes an object to an Extended JSON string, and reparse it as a JavaScript object.
*
* @param value - The object to serialize
* @param options - Optional settings passed to the `stringify` function
*/
export function serialize(value: SerializableTypes, options?: EJSON.Options): Document {
options = options || {};
return JSON.parse(stringify(value, options));
}
/**
* Deserializes an Extended JSON object into a plain JavaScript object with native/BSON types
*
* @param ejson - The Extended JSON object to deserialize
* @param options - Optional settings passed to the parse method
*/
export function deserialize(ejson: Document, options?: EJSON.Options): SerializableTypes {
options = options || {};
return parse(JSON.stringify(ejson), options);
}
}
/** @public */
const EJSON: {
parse: typeof parse;
stringify: typeof stringify;
serialize: typeof EJSONserialize;
deserialize: typeof EJSONdeserialize;
} = Object.create(null);
EJSON.parse = parse;
EJSON.stringify = stringify;
EJSON.serialize = EJSONserialize;
EJSON.deserialize = EJSONdeserialize;
Object.freeze(EJSON);
export { EJSON };

@@ -14,3 +14,9 @@ import type { EJSONOptions } from './extended_json';

export class Int32 {
_bsontype!: 'Int32';
get _bsontype(): 'Int32' {
return 'Int32';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -24,4 +30,2 @@ value!: number;

constructor(value: number | string) {
if (!(this instanceof Int32)) return new Int32(value);
if ((value as unknown) instanceof Number) {

@@ -71,3 +75,1 @@ value = value.valueOf();

}
Object.defineProperty(Int32.prototype, '_bsontype', { value: 'Int32' });
import type { EJSONOptions } from './extended_json';
import { isObjectLike } from './parser/utils';
import type { Timestamp } from './timestamp';

@@ -103,6 +102,14 @@

export class Long {
_bsontype!: 'Long';
get _bsontype(): 'Long' {
return 'Long';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}
/** An indicator used to reliably determine if an object is a Long or not. */
__isLong__!: true;
get __isLong__(): boolean {
return true;
}

@@ -138,4 +145,2 @@ /**

constructor(low: number | bigint | string = 0, high?: number | boolean, unsigned?: boolean) {
if (!(this instanceof Long)) return new Long(low, high, unsigned);
if (typeof low === 'bigint') {

@@ -150,9 +155,2 @@ Object.assign(this, Long.fromBigInt(low, !!high));

}
Object.defineProperty(this, '__isLong__', {
value: true,
configurable: false,
writable: false,
enumerable: false
});
}

@@ -338,3 +336,8 @@

static isLong(value: unknown): value is Long {
return isObjectLike(value) && value['__isLong__'] === true;
return (
value != null &&
typeof value === 'object' &&
'__isLong__' in value &&
value.__isLong__ === true
);
}

@@ -1042,4 +1045,1 @@

}
Object.defineProperty(Long.prototype, '__isLong__', { value: true });
Object.defineProperty(Long.prototype, '_bsontype', { value: 'Long' });

@@ -12,7 +12,9 @@ /** @public */

export class MaxKey {
_bsontype!: 'MaxKey';
constructor() {
if (!(this instanceof MaxKey)) return new MaxKey();
get _bsontype(): 'MaxKey' {
return 'MaxKey';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -38,3 +40,1 @@ /** @internal */

}
Object.defineProperty(MaxKey.prototype, '_bsontype', { value: 'MaxKey' });

@@ -12,7 +12,9 @@ /** @public */

export class MinKey {
_bsontype!: 'MinKey';
constructor() {
if (!(this instanceof MinKey)) return new MinKey();
get _bsontype(): 'MinKey' {
return 'MinKey';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -38,3 +40,1 @@ /** @internal */

}
Object.defineProperty(MinKey.prototype, '_bsontype', { value: 'MinKey' });

@@ -1,5 +0,4 @@

import { Buffer } from 'buffer';
import { ensureBuffer } from './ensure_buffer';
import { BSONTypeError } from './error';
import { deprecate, isUint8Array, randomBytes } from './parser/utils';
import { isUint8Array } from './parser/utils';
import { BSONDataView, ByteUtils } from './utils/byte_utils';

@@ -14,3 +13,3 @@ // Regular expression that checks for hex value

export interface ObjectIdLike {
id: string | Buffer;
id: string | Uint8Array;
__id?: string;

@@ -33,6 +32,12 @@ toHexString(): string;

export class ObjectId {
_bsontype!: 'ObjectID';
get _bsontype(): 'ObjectId' {
return 'ObjectId';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}
/** @internal */
static index = Math.floor(Math.random() * 0xffffff);
private static index = Math.floor(Math.random() * 0xffffff);

@@ -42,3 +47,3 @@ static cacheHexString: boolean;

/** ObjectId Bytes @internal */
private [kId]!: Buffer;
private [kId]!: Uint8Array;
/** ObjectId hexString cache @internal */

@@ -52,5 +57,3 @@ private __id?: string;

*/
constructor(inputId?: string | number | ObjectId | ObjectIdLike | Buffer | Uint8Array) {
if (!(this instanceof ObjectId)) return new ObjectId(inputId);
constructor(inputId?: string | number | ObjectId | ObjectIdLike | Uint8Array) {
// workingId is set based on type of input and whether valid id exists for the input

@@ -65,3 +68,3 @@ let workingId;

if ('toHexString' in inputId && typeof inputId.toHexString === 'function') {
workingId = Buffer.from(inputId.toHexString(), 'hex');
workingId = ByteUtils.fromHex(inputId.toHexString());
} else {

@@ -81,6 +84,7 @@ workingId = inputId.id;

// If intstanceof matches we can escape calling ensure buffer in Node.js environments
this[kId] = workingId instanceof Buffer ? workingId : ensureBuffer(workingId);
this[kId] = ByteUtils.toLocalBufferType(workingId);
} else if (typeof workingId === 'string') {
if (workingId.length === 12) {
const bytes = Buffer.from(workingId);
// TODO(NODE-4361): Remove string of length 12 support
const bytes = ByteUtils.fromUTF8(workingId);
if (bytes.byteLength === 12) {

@@ -92,3 +96,3 @@ this[kId] = bytes;

} else if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
this[kId] = Buffer.from(workingId, 'hex');
this[kId] = ByteUtils.fromHex(workingId);
} else {

@@ -104,3 +108,3 @@ throw new BSONTypeError(

if (ObjectId.cacheHexString) {
this.__id = this.id.toString('hex');
this.__id = ByteUtils.toHex(this.id);
}

@@ -113,26 +117,13 @@ }

*/
get id(): Buffer {
get id(): Uint8Array {
return this[kId];
}
set id(value: Buffer) {
set id(value: Uint8Array) {
this[kId] = value;
if (ObjectId.cacheHexString) {
this.__id = value.toString('hex');
this.__id = ByteUtils.toHex(value);
}
}
/**
* The generation time of this ObjectId instance
* @deprecated Please use getTimestamp / createFromTime which returns an int32 epoch
*/
get generationTime(): number {
return this.id.readInt32BE(0);
}
set generationTime(value: number) {
// Encode time into first 4 bytes
this.id.writeUInt32BE(value, 0);
}
/** Returns the ObjectId id as a 24 character hex string representation */

@@ -144,3 +135,3 @@ toHexString(): string {

const hexString = this.id.toString('hex');
const hexString = ByteUtils.toHex(this.id);

@@ -156,7 +147,5 @@ if (ObjectId.cacheHexString && !this.__id) {

* Update the ObjectId index
* @privateRemarks
* Used in generating new ObjectId's on the driver
* @internal
*/
static getInc(): number {
private static getInc(): number {
return (ObjectId.index = (ObjectId.index + 1) % 0xffffff);

@@ -170,3 +159,3 @@ }

*/
static generate(time?: number): Buffer {
static generate(time?: number): Uint8Array {
if ('number' !== typeof time) {

@@ -177,10 +166,10 @@ time = Math.floor(Date.now() / 1000);

const inc = ObjectId.getInc();
const buffer = Buffer.alloc(12);
const buffer = ByteUtils.allocate(12);
// 4-byte timestamp
buffer.writeUInt32BE(time, 0);
BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
// set PROCESS_UNIQUE if yet not initialized
if (PROCESS_UNIQUE === null) {
PROCESS_UNIQUE = randomBytes(5);
PROCESS_UNIQUE = ByteUtils.randomBytes(5);
}

@@ -204,9 +193,9 @@

/**
* Converts the id into a 24 character hex string for printing
*
* @param format - The Buffer toString format parameter.
* Converts the id into a 24 character hex string for printing, unless encoding is provided.
* @param encoding - hex or base64
*/
toString(format?: string): string {
toString(encoding?: 'hex' | 'base64'): string {
// Is the id a buffer then use the buffer toString method to return the format
if (format) return this.id.toString(format);
if (encoding === 'base64') return ByteUtils.toBase64(this.id);
if (encoding === 'hex') return this.toHexString();
return this.toHexString();

@@ -231,3 +220,3 @@ }

if (otherId instanceof ObjectId) {
return this[kId][11] === otherId[kId][11] && this[kId].equals(otherId[kId]);
return this[kId][11] === otherId[kId][11] && ByteUtils.equals(this[kId], otherId[kId]);
}

@@ -241,3 +230,3 @@

) {
return otherId === Buffer.prototype.toString.call(this.id, 'latin1');
return ByteUtils.equals(this.id, ByteUtils.fromISO88591(otherId));
}

@@ -250,3 +239,3 @@

if (typeof otherId === 'string' && ObjectId.isValid(otherId) && otherId.length === 12) {
return Buffer.from(otherId).equals(this.id);
return ByteUtils.equals(ByteUtils.fromUTF8(otherId), this.id);
}

@@ -270,3 +259,3 @@

const timestamp = new Date();
const time = this.id.readUInt32BE(0);
const time = BSONDataView.fromUint8Array(this.id).getUint32(0, false);
timestamp.setTime(Math.floor(time) * 1000);

@@ -287,5 +276,5 @@ return timestamp;

static createFromTime(time: number): ObjectId {
const buffer = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
const buffer = ByteUtils.fromNumberArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
// Encode time into first 4 bytes
buffer.writeUInt32BE(time, 0);
BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
// Return the new objectId

@@ -308,3 +297,3 @@ return new ObjectId(buffer);

return new ObjectId(Buffer.from(hexString, 'hex'));
return new ObjectId(ByteUtils.fromHex(hexString));
}

@@ -317,3 +306,3 @@

*/
static isValid(id: string | number | ObjectId | ObjectIdLike | Buffer | Uint8Array): boolean {
static isValid(id: string | number | ObjectId | ObjectIdLike | Uint8Array): boolean {
if (id == null) return false;

@@ -354,23 +343,1 @@

}
// Deprecated methods
Object.defineProperty(ObjectId.prototype, 'generate', {
value: deprecate(
(time: number) => ObjectId.generate(time),
'Please use the static `ObjectId.generate(time)` instead'
)
});
Object.defineProperty(ObjectId.prototype, 'getInc', {
value: deprecate(() => ObjectId.getInc(), 'Please use the static `ObjectId.getInc()` instead')
});
Object.defineProperty(ObjectId.prototype, 'get_inc', {
value: deprecate(() => ObjectId.getInc(), 'Please use the static `ObjectId.getInc()` instead')
});
Object.defineProperty(ObjectId, 'get_inc', {
value: deprecate(() => ObjectId.getInc(), 'Please use the static `ObjectId.getInc()` instead')
});
Object.defineProperty(ObjectId.prototype, '_bsontype', { value: 'ObjectID' });

@@ -1,8 +0,8 @@

import { Buffer } from 'buffer';
import { Binary } from '../binary';
import type { Document } from '../bson';
import * as constants from '../constants';
import { isAnyArrayBuffer, isDate, isRegExp, normalizedFunctionString } from './utils';
import { ByteUtils } from '../utils/byte_utils';
import { isAnyArrayBuffer, isDate, isRegExp } from './utils';
export function calculateObjectSize(
export function internalCalculateObjectSize(
object: Document,

@@ -32,3 +32,3 @@ serializeFunctions?: boolean,

// Calculate size
for (const key in object) {
for (const key of Object.keys(object)) {
totalLength += calculateElement(key, object[key], serializeFunctions, false, ignoreUndefined);

@@ -57,3 +57,3 @@ }

case 'string':
return 1 + Buffer.byteLength(name, 'utf8') + 1 + 4 + Buffer.byteLength(value, 'utf8') + 1;
return 1 + ByteUtils.utf8ByteLength(name) + 1 + 4 + ByteUtils.utf8ByteLength(value) + 1;
case 'number':

@@ -67,23 +67,23 @@ if (

// 32 bit
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (4 + 1);
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (4 + 1);
} else {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1);
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (8 + 1);
}
} else {
// 64 bit
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1);
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (8 + 1);
}
case 'undefined':
if (isArray || !ignoreUndefined)
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + 1;
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + 1;
return 0;
case 'boolean':
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (1 + 1);
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (1 + 1);
case 'object':
if (value == null || value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + 1;
} else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (12 + 1);
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + 1;
} else if (value['_bsontype'] === 'ObjectId') {
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (12 + 1);
} else if (value instanceof Date || isDate(value)) {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1);
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (8 + 1);
} else if (

@@ -95,3 +95,3 @@ ArrayBuffer.isView(value) ||

return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (1 + 4 + 1) + value.byteLength
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (1 + 4 + 1) + value.byteLength
);

@@ -103,5 +103,5 @@ } else if (

) {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1);
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (8 + 1);
} else if (value['_bsontype'] === 'Decimal128') {
return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (16 + 1);
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (16 + 1);
} else if (value['_bsontype'] === 'Code') {

@@ -111,16 +111,16 @@ // Calculate size depending on the availability of a scope

return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
1 +
4 +
4 +
Buffer.byteLength(value.code.toString(), 'utf8') +
ByteUtils.utf8ByteLength(value.code.toString()) +
1 +
calculateObjectSize(value.scope, serializeFunctions, ignoreUndefined)
internalCalculateObjectSize(value.scope, serializeFunctions, ignoreUndefined)
);
} else {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
1 +
4 +
Buffer.byteLength(value.code.toString(), 'utf8') +
ByteUtils.utf8ByteLength(value.code.toString()) +
1

@@ -134,3 +134,3 @@ );

return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
(binary.position + 1 + 4 + 1 + 4)

@@ -140,3 +140,3 @@ );

return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (binary.position + 1 + 4 + 1)
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (binary.position + 1 + 4 + 1)
);

@@ -146,4 +146,4 @@ }

return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
Buffer.byteLength(value.value, 'utf8') +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
ByteUtils.utf8ByteLength(value.value) +
4 +

@@ -169,11 +169,11 @@ 1 +

return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
1 +
calculateObjectSize(ordered_values, serializeFunctions, ignoreUndefined)
internalCalculateObjectSize(ordered_values, serializeFunctions, ignoreUndefined)
);
} else if (value instanceof RegExp || isRegExp(value)) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
1 +
Buffer.byteLength(value.source, 'utf8') +
ByteUtils.utf8ByteLength(value.source) +
1 +

@@ -187,7 +187,7 @@ (value.global ? 1 : 0) +

return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
1 +
Buffer.byteLength(value.pattern, 'utf8') +
ByteUtils.utf8ByteLength(value.pattern) +
1 +
Buffer.byteLength(value.options, 'utf8') +
ByteUtils.utf8ByteLength(value.options) +
1

@@ -197,4 +197,4 @@ );

return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
calculateObjectSize(value, serializeFunctions, ignoreUndefined) +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
internalCalculateObjectSize(value, serializeFunctions, ignoreUndefined) +
1

@@ -204,34 +204,10 @@ );

case 'function':
// WTF for 0.4.X where typeof /someregexp/ === 'function'
if (value instanceof RegExp || isRegExp(value) || String.call(value) === '[object RegExp]') {
if (serializeFunctions) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
1 +
Buffer.byteLength(value.source, 'utf8') +
1 +
(value.global ? 1 : 0) +
(value.ignoreCase ? 1 : 0) +
(value.multiline ? 1 : 0) +
4 +
ByteUtils.utf8ByteLength(value.toString()) +
1
);
} else {
if (serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
4 +
4 +
Buffer.byteLength(normalizedFunctionString(value), 'utf8') +
1 +
calculateObjectSize(value.scope, serializeFunctions, ignoreUndefined)
);
} else if (serializeFunctions) {
return (
(name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) +
1 +
4 +
Buffer.byteLength(normalizedFunctionString(value), 'utf8') +
1
);
}
}

@@ -238,0 +214,0 @@ }

@@ -1,2 +0,1 @@

import { Buffer } from 'buffer';
import { Binary } from '../binary';

@@ -18,2 +17,3 @@ import type { Document } from '../bson';

import { Timestamp } from '../timestamp';
import { ByteUtils } from '../utils/byte_utils';
import { validateUtf8 } from '../validate_utf8';

@@ -23,12 +23,2 @@

export interface DeserializeOptions {
/** evaluate functions in the BSON document scoped to the object deserialized. */
evalFunctions?: boolean;
/** cache evaluated functions for reuse. */
cacheFunctions?: boolean;
/**
* use a crc32 code for caching, otherwise use the string of the function.
* @deprecated this option to use the crc32 function never worked as intended
* due to the fact that the crc32 function itself was never implemented.
* */
cacheFunctionsCrc32?: boolean;
/** when deserializing a Long will fit it into a Number if it's smaller than 53 bits */

@@ -72,6 +62,4 @@ promoteLongs?: boolean;

const functionCache: { [hash: string]: Function } = {};
export function deserialize(
buffer: Buffer,
export function internalDeserialize(
buffer: Uint8Array,
options: DeserializeOptions,

@@ -121,3 +109,3 @@ isArray?: boolean

function deserializeObject(
buffer: Buffer,
buffer: Uint8Array,
index: number,

@@ -127,5 +115,2 @@ options: DeserializeOptions,

) {
const evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
const cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
const fieldsAsRaw = options['fieldsAsRaw'] == null ? null : options['fieldsAsRaw'];

@@ -224,3 +209,3 @@

// Represents the key
const name = isArray ? arrayIndex++ : buffer.toString('utf8', index, i);
const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer.subarray(index, i));

@@ -258,4 +243,4 @@ // shouldValidateKey is true if the key should be validated, false otherwise

} else if (elementType === constants.BSON_DATA_OID) {
const oid = Buffer.alloc(12);
buffer.copy(oid, 0, index, index + 12);
const oid = ByteUtils.allocate(12);
oid.set(buffer.subarray(index, index + 12));
value = new ObjectId(oid);

@@ -324,3 +309,3 @@ index = index + 12;

(buffer[index + 3] << 24);
let arrayOptions = options;
let arrayOptions: DeserializeOptions = options;

@@ -332,12 +317,5 @@ // Stop index

if (fieldsAsRaw && fieldsAsRaw[name]) {
arrayOptions = {};
for (const n in options) {
(
arrayOptions as {
[key: string]: DeserializeOptions[keyof DeserializeOptions];
}
)[n] = options[n as keyof DeserializeOptions];
}
arrayOptions['raw'] = true;
arrayOptions = { ...options, raw: true };
}
if (!globalUTFValidation) {

@@ -379,15 +357,9 @@ arrayOptions = { ...arrayOptions, validation: { utf8: shouldValidateKey } };

// Buffer to contain the decimal bytes
const bytes = Buffer.alloc(16);
const bytes = ByteUtils.allocate(16);
// Copy the next 16 bytes into the bytes buffer
buffer.copy(bytes, 0, index, index + 16);
bytes.set(buffer.subarray(index, index + 16), 0);
// Update index
index = index + 16;
// Assign the new Decimal128 value
const decimal128 = new Decimal128(bytes) as Decimal128 | { toObject(): unknown };
// If we have an alternative mapper use that
if ('toObject' in decimal128 && typeof decimal128.toObject === 'function') {
value = decimal128.toObject();
} else {
value = decimal128;
}
value = new Decimal128(bytes);
} else if (elementType === constants.BSON_DATA_BINARY) {

@@ -427,3 +399,3 @@ let binarySize =

if (promoteBuffers && promoteValues) {
value = buffer.slice(index, index + binarySize);
value = ByteUtils.toLocalBufferType(buffer.slice(index, index + binarySize));
} else {

@@ -436,3 +408,3 @@ value = new Binary(buffer.slice(index, index + binarySize), subType);

} else {
const _buffer = Buffer.alloc(binarySize);
const _buffer = ByteUtils.allocate(binarySize);
// If we have subtype 2 skip the 4 bytes for the size

@@ -479,3 +451,3 @@ if (subType === Binary.SUBTYPE_BYTE_ARRAY) {

// Return the C string
const source = buffer.toString('utf8', index, i);
const source = ByteUtils.toUTF8(buffer.subarray(index, i));
// Create the regexp

@@ -493,3 +465,3 @@ index = i + 1;

// Return the C string
const regExpOptions = buffer.toString('utf8', index, i);
const regExpOptions = ByteUtils.toUTF8(buffer.subarray(index, i));
index = i + 1;

@@ -526,3 +498,3 @@

// Return the C string
const source = buffer.toString('utf8', index, i);
const source = ByteUtils.toUTF8(buffer.subarray(index, i));
index = i + 1;

@@ -539,3 +511,3 @@

// Return the C string
const regExpOptions = buffer.toString('utf8', index, i);
const regExpOptions = ByteUtils.toUTF8(buffer.subarray(index, i));
index = i + 1;

@@ -562,14 +534,17 @@

} else if (elementType === constants.BSON_DATA_TIMESTAMP) {
const lowBits =
buffer[index++] |
(buffer[index++] << 8) |
(buffer[index++] << 16) |
(buffer[index++] << 24);
const highBits =
buffer[index++] |
(buffer[index++] << 8) |
(buffer[index++] << 16) |
(buffer[index++] << 24);
// We intentionally **do not** use bit shifting here
// Bit shifting in javascript coerces numbers to **signed** int32s
// We need to keep i, and t unsigned
const i =
buffer[index++] +
buffer[index++] * (1 << 8) +
buffer[index++] * (1 << 16) +
buffer[index++] * (1 << 24);
const t =
buffer[index++] +
buffer[index++] * (1 << 8) +
buffer[index++] * (1 << 16) +
buffer[index++] * (1 << 24);
value = new Timestamp(lowBits, highBits);
value = new Timestamp({ i, t });
} else if (elementType === constants.BSON_DATA_MIN_KEY) {

@@ -599,14 +574,3 @@ value = new MinKey();

// If we are evaluating the functions
if (evalFunctions) {
// If we have cache enabled let's look for the md5 of the function in the cache
if (cacheFunctions) {
// Got to do this to avoid V8 deoptimizing the call due to finding eval
value = isolateEval(functionString, functionCache, object);
} else {
value = isolateEval(functionString);
}
} else {
value = new Code(functionString);
}
value = new Code(functionString);

@@ -674,16 +638,3 @@ // Update parse index position

// If we are evaluating the functions
if (evalFunctions) {
// If we have cache enabled let's look for the md5 of the function in the cache
if (cacheFunctions) {
// Got to do this to avoid V8 deoptimizing the call due to finding eval
value = isolateEval(functionString, functionCache, object);
} else {
value = isolateEval(functionString);
}
value.scope = scopeObject;
} else {
value = new Code(functionString, scopeObject);
}
value = new Code(functionString, scopeObject);
} else if (elementType === constants.BSON_DATA_DBPOINTER) {

@@ -709,3 +660,3 @@ // Get the code string size

}
const namespace = buffer.toString('utf8', index, index + stringSize - 1);
const namespace = ByteUtils.toUTF8(buffer.subarray(index, index + stringSize - 1));
// Update parse index position

@@ -715,4 +666,4 @@ index = index + stringSize;

// Read the oid
const oidBuffer = Buffer.alloc(12);
buffer.copy(oidBuffer, 0, index, index + 12);
const oidBuffer = ByteUtils.allocate(12);
oidBuffer.set(buffer.subarray(index, index + 12), 0);
const oid = new ObjectId(oidBuffer);

@@ -762,26 +713,4 @@

/**
* Ensure eval is isolated, store the result in functionCache.
*
* @internal
*/
function isolateEval(
functionString: string,
functionCache?: { [hash: string]: Function },
object?: Document
) {
// eslint-disable-next-line @typescript-eslint/no-implied-eval
if (!functionCache) return new Function(functionString);
// Check for cache hit, eval if missing and return cached function
if (functionCache[functionString] == null) {
// eslint-disable-next-line @typescript-eslint/no-implied-eval
functionCache[functionString] = new Function(functionString);
}
// Set the object
return functionCache[functionString].bind(object);
}
function getValidatedString(
buffer: Buffer,
buffer: Uint8Array,
start: number,

@@ -791,3 +720,3 @@ end: number,

) {
const value = buffer.toString('utf8', start, end);
const value = ByteUtils.toUTF8(buffer.subarray(start, end));
// if utf8 validation is on, do the check

@@ -794,0 +723,0 @@ if (shouldValidateUtf8) {

@@ -1,2 +0,1 @@

import type { Buffer } from 'buffer';
import { Binary } from '../binary';

@@ -9,12 +8,11 @@ import type { BSONSymbol, DBRef, Document, MaxKey } from '../bson';

import type { Double } from '../double';
import { ensureBuffer } from '../ensure_buffer';
import { BSONError, BSONTypeError } from '../error';
import { isBSONType } from '../extended_json';
import type { Int32 } from '../int_32';
import { Long } from '../long';
import { Map } from '../map';
import type { MinKey } from '../min_key';
import type { ObjectId } from '../objectid';
import type { BSONRegExp } from '../regexp';
import { ByteUtils } from '../utils/byte_utils';
import {
isAnyArrayBuffer,
isBigInt64Array,

@@ -25,4 +23,3 @@ isBigUInt64Array,

isRegExp,
isUint8Array,
normalizedFunctionString
isUint8Array
} from './utils';

@@ -53,15 +50,7 @@

function serializeString(
buffer: Buffer,
key: string,
value: string,
index: number,
isArray?: boolean
) {
function serializeString(buffer: Uint8Array, key: string, value: string, index: number) {
// Encode String type
buffer[index++] = constants.BSON_DATA_STRING;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -71,3 +60,3 @@ index = index + numberOfWrittenBytes + 1;

// Write the string
const size = buffer.write(value, index + 4, undefined, 'utf8');
const size = ByteUtils.encodeUTF8Into(buffer, value, index + 4);
// Write the size of the string to buffer

@@ -85,58 +74,39 @@ buffer[index + 3] = ((size + 1) >> 24) & 0xff;

const SPACE_FOR_FLOAT64 = new Uint8Array(8);
const DV_FOR_FLOAT64 = new DataView(
SPACE_FOR_FLOAT64.buffer,
SPACE_FOR_FLOAT64.byteOffset,
SPACE_FOR_FLOAT64.byteLength
);
function serializeNumber(
buffer: Buffer,
key: string,
value: number,
index: number,
isArray?: boolean
) {
// We have an integer value
// TODO(NODE-2529): Add support for big int
if (
Number.isInteger(value) &&
value >= constants.BSON_INT32_MIN &&
value <= constants.BSON_INT32_MAX
) {
// If the value fits in 32 bits encode as int32
// Set int type 32 bits or less
buffer[index++] = constants.BSON_DATA_INT;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
// Encode the name
index = index + numberOfWrittenBytes;
buffer[index++] = 0;
// Write the int value
buffer[index++] = value & 0xff;
buffer[index++] = (value >> 8) & 0xff;
buffer[index++] = (value >> 16) & 0xff;
buffer[index++] = (value >> 24) & 0xff;
const NUMBER_SPACE = new DataView(new ArrayBuffer(8), 0, 8);
const FOUR_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 4);
const EIGHT_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 8);
function serializeNumber(buffer: Uint8Array, key: string, value: number, index: number) {
const isNegativeZero = Object.is(value, -0);
const type =
!isNegativeZero &&
Number.isSafeInteger(value) &&
value <= constants.BSON_INT32_MAX &&
value >= constants.BSON_INT32_MIN
? constants.BSON_DATA_INT
: constants.BSON_DATA_NUMBER;
if (type === constants.BSON_DATA_INT) {
NUMBER_SPACE.setInt32(0, value, true);
} else {
// Encode as double
buffer[index++] = constants.BSON_DATA_NUMBER;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
// Encode the name
index = index + numberOfWrittenBytes;
buffer[index++] = 0;
// Write float
DV_FOR_FLOAT64.setFloat64(0, value, true);
buffer.set(SPACE_FOR_FLOAT64, index);
// Adjust index
index = index + 8;
NUMBER_SPACE.setFloat64(0, value, true);
}
const bytes =
type === constants.BSON_DATA_INT ? FOUR_BYTE_VIEW_ON_NUMBER : EIGHT_BYTE_VIEW_ON_NUMBER;
buffer[index++] = type;
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
index = index + numberOfWrittenBytes;
buffer[index++] = 0x00;
buffer.set(bytes, index);
index += bytes.byteLength;
return index;
}
function serializeNull(buffer: Buffer, key: string, _: unknown, index: number, isArray?: boolean) {
function serializeNull(buffer: Uint8Array, key: string, _: unknown, index: number) {
// Set long type

@@ -146,5 +116,3 @@ buffer[index++] = constants.BSON_DATA_NULL;

// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);

@@ -157,15 +125,7 @@ // Encode the name

function serializeBoolean(
buffer: Buffer,
key: string,
value: boolean,
index: number,
isArray?: boolean
) {
function serializeBoolean(buffer: Uint8Array, key: string, value: boolean, index: number) {
// Write the type
buffer[index++] = constants.BSON_DATA_BOOLEAN;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -179,9 +139,7 @@ index = index + numberOfWrittenBytes;

function serializeDate(buffer: Buffer, key: string, value: Date, index: number, isArray?: boolean) {
function serializeDate(buffer: Uint8Array, key: string, value: Date, index: number) {
// Write the type
buffer[index++] = constants.BSON_DATA_DATE;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -208,15 +166,7 @@ index = index + numberOfWrittenBytes;

function serializeRegExp(
buffer: Buffer,
key: string,
value: RegExp,
index: number,
isArray?: boolean
) {
function serializeRegExp(buffer: Uint8Array, key: string, value: RegExp, index: number) {
// Write the type
buffer[index++] = constants.BSON_DATA_REGEXP;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);

@@ -230,3 +180,3 @@ // Encode the name

// Adjust the index
index = index + buffer.write(value.source, index, undefined, 'utf8');
index = index + ByteUtils.encodeUTF8Into(buffer, value.source, index);
// Write zero

@@ -244,15 +194,7 @@ buffer[index++] = 0x00;

function serializeBSONRegExp(
buffer: Buffer,
key: string,
value: BSONRegExp,
index: number,
isArray?: boolean
) {
function serializeBSONRegExp(buffer: Uint8Array, key: string, value: BSONRegExp, index: number) {
// Write the type
buffer[index++] = constants.BSON_DATA_REGEXP;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -270,7 +212,8 @@ index = index + numberOfWrittenBytes;

// Adjust the index
index = index + buffer.write(value.pattern, index, undefined, 'utf8');
index = index + ByteUtils.encodeUTF8Into(buffer, value.pattern, index);
// Write zero
buffer[index++] = 0x00;
// Write the options
index = index + buffer.write(value.options.split('').sort().join(''), index, undefined, 'utf8');
const sortedOptions = value.options.split('').sort().join('');
index = index + ByteUtils.encodeUTF8Into(buffer, sortedOptions, index);
// Add ending zero

@@ -281,9 +224,3 @@ buffer[index++] = 0x00;

function serializeMinMax(
buffer: Buffer,
key: string,
value: MinKey | MaxKey,
index: number,
isArray?: boolean
) {
function serializeMinMax(buffer: Uint8Array, key: string, value: MinKey | MaxKey, index: number) {
// Write the type of either min or max key

@@ -299,5 +236,3 @@ if (value === null) {

// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -309,15 +244,7 @@ index = index + numberOfWrittenBytes;

function serializeObjectId(
buffer: Buffer,
key: string,
value: ObjectId,
index: number,
isArray?: boolean
) {
function serializeObjectId(buffer: Uint8Array, key: string, value: ObjectId, index: number) {
// Write the type
buffer[index++] = constants.BSON_DATA_OID;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);

@@ -329,7 +256,3 @@ // Encode the name

// Write the objectId into the shared buffer
if (typeof value.id === 'string') {
buffer.write(value.id, index, undefined, 'binary');
} else if (isUint8Array(value.id)) {
// Use the standard JS methods here because buffer.copy() is buggy with the
// browser polyfill
if (isUint8Array(value.id)) {
buffer.set(value.id.subarray(0, 12), index);

@@ -344,15 +267,7 @@ } else {

function serializeBuffer(
buffer: Buffer,
key: string,
value: Buffer | Uint8Array,
index: number,
isArray?: boolean
) {
function serializeBuffer(buffer: Uint8Array, key: string, value: Uint8Array, index: number) {
// Write the type
buffer[index++] = constants.BSON_DATA_BINARY;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -371,3 +286,3 @@ index = index + numberOfWrittenBytes;

// Copy the content form the binary field to the buffer
buffer.set(ensureBuffer(value), index);
buffer.set(value, index);
// Adjust the index

@@ -379,25 +294,22 @@ index = index + size;

function serializeObject(
buffer: Buffer,
buffer: Uint8Array,
key: string,
value: Document,
index: number,
checkKeys = false,
depth = 0,
serializeFunctions = false,
ignoreUndefined = true,
isArray = false,
path: Document[] = []
checkKeys: boolean,
depth: number,
serializeFunctions: boolean,
ignoreUndefined: boolean,
path: Set<Document>
) {
for (let i = 0; i < path.length; i++) {
if (path[i] === value) throw new BSONError('cyclic dependency detected');
if (path.has(value)) {
throw new BSONError('Cannot convert circular structure to BSON');
}
// Push value to stack
path.push(value);
path.add(value);
// Write the type
buffer[index++] = Array.isArray(value) ? constants.BSON_DATA_ARRAY : constants.BSON_DATA_OBJECT;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -416,19 +328,12 @@ index = index + numberOfWrittenBytes;

);
// Pop stack
path.pop();
path.delete(value);
return endIndex;
}
function serializeDecimal128(
buffer: Buffer,
key: string,
value: Decimal128,
index: number,
isArray?: boolean
) {
function serializeDecimal128(buffer: Uint8Array, key: string, value: Decimal128, index: number) {
buffer[index++] = constants.BSON_DATA_DECIMAL128;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -438,4 +343,2 @@ index = index + numberOfWrittenBytes;

// Write the data from the value
// Prefer the standard JS methods because their typechecking is not buggy,
// unlike the `buffer` polyfill's.
buffer.set(value.bytes.subarray(0, 16), index);

@@ -445,3 +348,3 @@ return index + 16;

function serializeLong(buffer: Buffer, key: string, value: Long, index: number, isArray?: boolean) {
function serializeLong(buffer: Uint8Array, key: string, value: Long, index: number) {
// Write the type

@@ -451,5 +354,3 @@ buffer[index++] =

// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -474,9 +375,3 @@ index = index + numberOfWrittenBytes;

function serializeInt32(
buffer: Buffer,
key: string,
value: Int32 | number,
index: number,
isArray?: boolean
) {
function serializeInt32(buffer: Uint8Array, key: string, value: Int32 | number, index: number) {
value = value.valueOf();

@@ -486,5 +381,3 @@ // Set int type 32 bits or less

// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -501,9 +394,3 @@ index = index + numberOfWrittenBytes;

function serializeDouble(
buffer: Buffer,
key: string,
value: Double,
index: number,
isArray?: boolean
) {
function serializeDouble(buffer: Uint8Array, key: string, value: Double, index: number) {
// Encode as double

@@ -513,5 +400,3 @@ buffer[index++] = constants.BSON_DATA_NUMBER;

// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);

@@ -523,4 +408,4 @@ // Encode the name

// Write float
DV_FOR_FLOAT64.setFloat64(0, value.value, true);
buffer.set(SPACE_FOR_FLOAT64, index);
NUMBER_SPACE.setFloat64(0, value.value, true);
buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);

@@ -532,16 +417,6 @@ // Adjust index

function serializeFunction(
buffer: Buffer,
key: string,
value: Function,
index: number,
_checkKeys = false,
_depth = 0,
isArray?: boolean
) {
function serializeFunction(buffer: Uint8Array, key: string, value: Function, index: number) {
buffer[index++] = constants.BSON_DATA_CODE;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -551,6 +426,6 @@ index = index + numberOfWrittenBytes;

// Function string
const functionString = normalizedFunctionString(value);
const functionString = value.toString();
// Write the string
const size = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
// Write the size of the string to buffer

@@ -569,3 +444,3 @@ buffer[index] = size & 0xff;

function serializeCode(
buffer: Buffer,
buffer: Uint8Array,
key: string,

@@ -578,3 +453,3 @@ value: Code,

ignoreUndefined = true,
isArray = false
path: Set<Document>
) {

@@ -585,5 +460,3 @@ if (value.scope && typeof value.scope === 'object') {

// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -598,7 +471,7 @@ index = index + numberOfWrittenBytes;

// Get the function string
const functionString = typeof value.code === 'string' ? value.code : value.code.toString();
const functionString = value.code;
// Index adjustment
index = index + 4;
// Write string into buffer
const codeSize = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
// Write the size of the string to buffer

@@ -614,3 +487,2 @@ buffer[index] = codeSize & 0xff;

//
// Serialize the scope value

@@ -624,3 +496,4 @@ const endIndex = serializeInto(

serializeFunctions,
ignoreUndefined
ignoreUndefined,
path
);

@@ -642,5 +515,3 @@ index = endIndex - 1;

// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -652,3 +523,3 @@ index = index + numberOfWrittenBytes;

// Write the string
const size = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
// Write the size of the string to buffer

@@ -668,15 +539,7 @@ buffer[index] = size & 0xff;

function serializeBinary(
buffer: Buffer,
key: string,
value: Binary,
index: number,
isArray?: boolean
) {
function serializeBinary(buffer: Uint8Array, key: string, value: Binary, index: number) {
// Write the type
buffer[index++] = constants.BSON_DATA_BINARY;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -686,3 +549,3 @@ index = index + numberOfWrittenBytes;

// Extract the buffer
const data = value.value(true) as Buffer | Uint8Array;
const data = value.buffer;
// Calculate size

@@ -716,15 +579,7 @@ let size = value.position;

function serializeSymbol(
buffer: Buffer,
key: string,
value: BSONSymbol,
index: number,
isArray?: boolean
) {
function serializeSymbol(buffer: Uint8Array, key: string, value: BSONSymbol, index: number) {
// Write the type
buffer[index++] = constants.BSON_DATA_SYMBOL;
// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
// Encode the name

@@ -734,3 +589,3 @@ index = index + numberOfWrittenBytes;

// Write the string
const size = buffer.write(value.value, index + 4, undefined, 'utf8') + 1;
const size = ByteUtils.encodeUTF8Into(buffer, value.value, index + 4) + 1;
// Write the size of the string to buffer

@@ -749,3 +604,3 @@ buffer[index] = size & 0xff;

function serializeDBRef(
buffer: Buffer,
buffer: Uint8Array,
key: string,

@@ -756,3 +611,3 @@ value: DBRef,

serializeFunctions: boolean,
isArray?: boolean
path: Set<Document>
) {

@@ -762,5 +617,3 @@ // Write the type

// Number of written bytes
const numberOfWrittenBytes = !isArray
? buffer.write(key, index, undefined, 'utf8')
: buffer.write(key, index, undefined, 'ascii');
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);

@@ -782,3 +635,12 @@ // Encode the name

output = Object.assign(output, value.fields);
const endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions);
const endIndex = serializeInto(
buffer,
output,
false,
index,
depth + 1,
serializeFunctions,
true,
path
);

@@ -797,16 +659,46 @@ // Calculate object size

export function serializeInto(
buffer: Buffer,
buffer: Uint8Array,
object: Document,
checkKeys = false,
startingIndex = 0,
depth = 0,
serializeFunctions = false,
ignoreUndefined = true,
path: Document[] = []
checkKeys: boolean,
startingIndex: number,
depth: number,
serializeFunctions: boolean,
ignoreUndefined: boolean,
path: Set<Document> | null
): number {
startingIndex = startingIndex || 0;
path = path || [];
if (path == null) {
// We are at the root input
if (object == null) {
// ONLY the root should turn into an empty document
// BSON Empty document has a size of 5 (LE)
buffer[0] = 0x05;
buffer[1] = 0x00;
buffer[2] = 0x00;
buffer[3] = 0x00;
// All documents end with null terminator
buffer[4] = 0x00;
return 5;
}
if (Array.isArray(object)) {
throw new BSONError('serialize does not support an array as the root input');
}
if (typeof object !== 'object') {
throw new BSONError('serialize does not support non-object as the root input');
} else if ('_bsontype' in object && typeof object._bsontype === 'string') {
throw new BSONError(`BSON types cannot be serialized as a document`);
} else if (
isDate(object) ||
isRegExp(object) ||
isUint8Array(object) ||
isAnyArrayBuffer(object)
) {
throw new BSONError(`date, regexp, typedarray, and arraybuffer cannot be BSON documents`);
}
path = new Set();
}
// Push the object to the path
path.push(object);
path.add(object);

@@ -829,22 +721,20 @@ // Start place to serialize into

if (typeof value === 'string') {
index = serializeString(buffer, key, value, index, true);
index = serializeString(buffer, key, value, index);
} else if (typeof value === 'number') {
index = serializeNumber(buffer, key, value, index, true);
index = serializeNumber(buffer, key, value, index);
} else if (typeof value === 'bigint') {
throw new BSONTypeError('Unsupported type BigInt, please use Decimal128');
} else if (typeof value === 'boolean') {
index = serializeBoolean(buffer, key, value, index, true);
index = serializeBoolean(buffer, key, value, index);
} else if (value instanceof Date || isDate(value)) {
index = serializeDate(buffer, key, value, index, true);
index = serializeDate(buffer, key, value, index);
} else if (value === undefined) {
index = serializeNull(buffer, key, value, index, true);
index = serializeNull(buffer, key, value, index);
} else if (value === null) {
index = serializeNull(buffer, key, value, index, true);
} else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
index = serializeObjectId(buffer, key, value, index, true);
index = serializeNull(buffer, key, value, index);
} else if (isUint8Array(value)) {
index = serializeBuffer(buffer, key, value, index, true);
index = serializeBuffer(buffer, key, value, index);
} else if (value instanceof RegExp || isRegExp(value)) {
index = serializeRegExp(buffer, key, value, index, true);
} else if (typeof value === 'object' && value['_bsontype'] == null) {
index = serializeRegExp(buffer, key, value, index);
} else if (typeof value === 'object' && value._bsontype == null) {
index = serializeObject(

@@ -859,18 +749,17 @@ buffer,

ignoreUndefined,
true,
path
);
} else if (
typeof value === 'object' &&
isBSONType(value) &&
value._bsontype === 'Decimal128'
) {
index = serializeDecimal128(buffer, key, value, index, true);
} else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
index = serializeLong(buffer, key, value, index, true);
} else if (value['_bsontype'] === 'Double') {
index = serializeDouble(buffer, key, value, index, true);
} else if (typeof value === 'object' && value[Symbol.for('@@mdb.bson.version')] == null) {
throw new BSONError('Unsupported BSON version, bson types must be from bson 5.0 or later');
} else if (value._bsontype === 'ObjectId') {
index = serializeObjectId(buffer, key, value, index);
} else if (value._bsontype === 'Decimal128') {
index = serializeDecimal128(buffer, key, value, index);
} else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
index = serializeLong(buffer, key, value, index);
} else if (value._bsontype === 'Double') {
index = serializeDouble(buffer, key, value, index);
} else if (typeof value === 'function' && serializeFunctions) {
index = serializeFunction(buffer, key, value, index, checkKeys, depth, true);
} else if (value['_bsontype'] === 'Code') {
index = serializeFunction(buffer, key, value, index);
} else if (value._bsontype === 'Code') {
index = serializeCode(

@@ -885,18 +774,18 @@ buffer,

ignoreUndefined,
true
path
);
} else if (value['_bsontype'] === 'Binary') {
index = serializeBinary(buffer, key, value, index, true);
} else if (value['_bsontype'] === 'Symbol') {
index = serializeSymbol(buffer, key, value, index, true);
} else if (value['_bsontype'] === 'DBRef') {
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, true);
} else if (value['_bsontype'] === 'BSONRegExp') {
index = serializeBSONRegExp(buffer, key, value, index, true);
} else if (value['_bsontype'] === 'Int32') {
index = serializeInt32(buffer, key, value, index, true);
} else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
index = serializeMinMax(buffer, key, value, index, true);
} else if (typeof value['_bsontype'] !== 'undefined') {
throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value['_bsontype'])}`);
} else if (value._bsontype === 'Binary') {
index = serializeBinary(buffer, key, value, index);
} else if (value._bsontype === 'Symbol') {
index = serializeSymbol(buffer, key, value, index);
} else if (value._bsontype === 'DBRef') {
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
} else if (value._bsontype === 'BSONRegExp') {
index = serializeBSONRegExp(buffer, key, value, index);
} else if (value._bsontype === 'Int32') {
index = serializeInt32(buffer, key, value, index);
} else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
index = serializeMinMax(buffer, key, value, index);
} else if (typeof value._bsontype !== 'undefined') {
throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
}

@@ -951,4 +840,2 @@ }

index = serializeNull(buffer, key, value, index);
} else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
index = serializeObjectId(buffer, key, value, index);
} else if (isUint8Array(value)) {

@@ -958,3 +845,3 @@ index = serializeBuffer(buffer, key, value, index);

index = serializeRegExp(buffer, key, value, index);
} else if (type === 'object' && value['_bsontype'] == null) {
} else if (type === 'object' && value._bsontype == null) {
index = serializeObject(

@@ -969,12 +856,15 @@ buffer,

ignoreUndefined,
false,
path
);
} else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
} else if (typeof value === 'object' && value[Symbol.for('@@mdb.bson.version')] == null) {
throw new BSONError('Unsupported BSON version, bson types must be from bson 5.0 or later');
} else if (value._bsontype === 'ObjectId') {
index = serializeObjectId(buffer, key, value, index);
} else if (type === 'object' && value._bsontype === 'Decimal128') {
index = serializeDecimal128(buffer, key, value, index);
} else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
} else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
index = serializeLong(buffer, key, value, index);
} else if (value['_bsontype'] === 'Double') {
} else if (value._bsontype === 'Double') {
index = serializeDouble(buffer, key, value, index);
} else if (value['_bsontype'] === 'Code') {
} else if (value._bsontype === 'Code') {
index = serializeCode(

@@ -988,20 +878,21 @@ buffer,

serializeFunctions,
ignoreUndefined
ignoreUndefined,
path
);
} else if (typeof value === 'function' && serializeFunctions) {
index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
} else if (value['_bsontype'] === 'Binary') {
index = serializeFunction(buffer, key, value, index);
} else if (value._bsontype === 'Binary') {
index = serializeBinary(buffer, key, value, index);
} else if (value['_bsontype'] === 'Symbol') {
} else if (value._bsontype === 'Symbol') {
index = serializeSymbol(buffer, key, value, index);
} else if (value['_bsontype'] === 'DBRef') {
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
} else if (value['_bsontype'] === 'BSONRegExp') {
} else if (value._bsontype === 'DBRef') {
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
} else if (value._bsontype === 'BSONRegExp') {
index = serializeBSONRegExp(buffer, key, value, index);
} else if (value['_bsontype'] === 'Int32') {
} else if (value._bsontype === 'Int32') {
index = serializeInt32(buffer, key, value, index);
} else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
} else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
index = serializeMinMax(buffer, key, value, index);
} else if (typeof value['_bsontype'] !== 'undefined') {
throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value['_bsontype'])}`);
} else if (typeof value._bsontype !== 'undefined') {
throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
}

@@ -1019,3 +910,3 @@ }

// Iterate over all the keys
for (const key in object) {
for (const key of Object.keys(object)) {
let value = object[key];

@@ -1061,4 +952,2 @@ // Is there an override value

index = serializeNull(buffer, key, value, index);
} else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
index = serializeObjectId(buffer, key, value, index);
} else if (isUint8Array(value)) {

@@ -1068,3 +957,3 @@ index = serializeBuffer(buffer, key, value, index);

index = serializeRegExp(buffer, key, value, index);
} else if (type === 'object' && value['_bsontype'] == null) {
} else if (type === 'object' && value._bsontype == null) {
index = serializeObject(

@@ -1079,12 +968,15 @@ buffer,

ignoreUndefined,
false,
path
);
} else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
} else if (typeof value === 'object' && value[Symbol.for('@@mdb.bson.version')] == null) {
throw new BSONError('Unsupported BSON version, bson types must be from bson 5.0 or later');
} else if (value._bsontype === 'ObjectId') {
index = serializeObjectId(buffer, key, value, index);
} else if (type === 'object' && value._bsontype === 'Decimal128') {
index = serializeDecimal128(buffer, key, value, index);
} else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
} else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
index = serializeLong(buffer, key, value, index);
} else if (value['_bsontype'] === 'Double') {
} else if (value._bsontype === 'Double') {
index = serializeDouble(buffer, key, value, index);
} else if (value['_bsontype'] === 'Code') {
} else if (value._bsontype === 'Code') {
index = serializeCode(

@@ -1098,20 +990,21 @@ buffer,

serializeFunctions,
ignoreUndefined
ignoreUndefined,
path
);
} else if (typeof value === 'function' && serializeFunctions) {
index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
} else if (value['_bsontype'] === 'Binary') {
index = serializeFunction(buffer, key, value, index);
} else if (value._bsontype === 'Binary') {
index = serializeBinary(buffer, key, value, index);
} else if (value['_bsontype'] === 'Symbol') {
} else if (value._bsontype === 'Symbol') {
index = serializeSymbol(buffer, key, value, index);
} else if (value['_bsontype'] === 'DBRef') {
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
} else if (value['_bsontype'] === 'BSONRegExp') {
} else if (value._bsontype === 'DBRef') {
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
} else if (value._bsontype === 'BSONRegExp') {
index = serializeBSONRegExp(buffer, key, value, index);
} else if (value['_bsontype'] === 'Int32') {
} else if (value._bsontype === 'Int32') {
index = serializeInt32(buffer, key, value, index);
} else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
} else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
index = serializeMinMax(buffer, key, value, index);
} else if (typeof value['_bsontype'] !== 'undefined') {
throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value['_bsontype'])}`);
} else if (typeof value._bsontype !== 'undefined') {
throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
}

@@ -1122,3 +1015,3 @@ }

// Remove the path
path.pop();
path.delete(object);

@@ -1125,0 +1018,0 @@ // Final padding byte for object

@@ -1,71 +0,1 @@

import { Buffer } from 'buffer';
import { getGlobal } from '../utils/global';
type RandomBytesFunction = (size: number) => Uint8Array;
/**
* Normalizes our expected stringified form of a function across versions of node
* @param fn - The function to stringify
*/
export function normalizedFunctionString(fn: Function): string {
return fn.toString().replace('function(', 'function (');
}
function isReactNative() {
const g = getGlobal<{ navigator?: { product?: string } }>();
return typeof g.navigator === 'object' && g.navigator.product === 'ReactNative';
}
const insecureRandomBytes: RandomBytesFunction = function insecureRandomBytes(size: number) {
const insecureWarning = isReactNative()
? 'BSON: For React Native please polyfill crypto.getRandomValues, e.g. using: https://www.npmjs.com/package/react-native-get-random-values.'
: 'BSON: No cryptographic implementation for random bytes present, falling back to a less secure implementation.';
console.warn(insecureWarning);
const result = Buffer.alloc(size);
for (let i = 0; i < size; ++i) result[i] = Math.floor(Math.random() * 256);
return result;
};
/* We do not want to have to include DOM types just for this check */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare let window: any;
declare let require: Function;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare let global: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare let process: any; // Used by @rollup/plugin-replace
const detectRandomBytes = (): RandomBytesFunction => {
if (process.browser) {
if (typeof window !== 'undefined') {
// browser crypto implementation(s)
const target = window.crypto || window.msCrypto; // allow for IE11
if (target && target.getRandomValues) {
return size => target.getRandomValues(Buffer.alloc(size));
}
}
if (typeof global !== 'undefined' && global.crypto && global.crypto.getRandomValues) {
// allow for RN packages such as https://www.npmjs.com/package/react-native-get-random-values to populate global
return size => global.crypto.getRandomValues(Buffer.alloc(size));
}
return insecureRandomBytes;
} else {
let requiredRandomBytes: RandomBytesFunction | null | undefined;
try {
requiredRandomBytes = require('crypto').randomBytes;
} catch (e) {
// keep the fallback
}
// NOTE: in transpiled cases the above require might return null/undefined
return requiredRandomBytes || insecureRandomBytes;
}
};
export const randomBytes = detectRandomBytes();
export function isAnyArrayBuffer(value: unknown): value is ArrayBuffer {

@@ -97,32 +27,4 @@ return ['[object ArrayBuffer]', '[object SharedArrayBuffer]'].includes(

/** Call to check if your environment has `Buffer` */
export function haveBuffer(): boolean {
return typeof global !== 'undefined' && typeof global.Buffer !== 'undefined';
}
// To ensure that 0.4 of node works correctly
export function isDate(d: unknown): d is Date {
return isObjectLike(d) && Object.prototype.toString.call(d) === '[object Date]';
return Object.prototype.toString.call(d) === '[object Date]';
}
/**
* @internal
* this is to solve the `'someKey' in x` problem where x is unknown.
* https://github.com/typescript-eslint/typescript-eslint/issues/1071#issuecomment-541955753
*/
export function isObjectLike(candidate: unknown): candidate is Record<string, unknown> {
return typeof candidate === 'object' && candidate !== null;
}
declare let console: { warn(...message: unknown[]): void };
export function deprecate<T extends Function>(fn: T, message: string): T {
let warned = false;
function deprecated(this: unknown, ...args: unknown[]) {
if (!warned) {
console.warn(message);
warned = true;
}
return fn.apply(this, args);
}
return deprecated as unknown as T;
}

@@ -28,3 +28,9 @@ import { BSONError, BSONTypeError } from './error';

export class BSONRegExp {
_bsontype!: 'BSONRegExp';
get _bsontype(): 'BSONRegExp' {
return 'BSONRegExp';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -38,4 +44,2 @@ pattern!: string;

constructor(pattern: string, options?: string) {
if (!(this instanceof BSONRegExp)) return new BSONRegExp(pattern, options);
this.pattern = pattern;

@@ -105,4 +109,11 @@ this.options = alphabetize(options ?? '');

}
/** @internal */
[Symbol.for('nodejs.util.inspect.custom')](): string {
return this.inspect();
}
inspect(): string {
return `new BSONRegExp(${JSON.stringify(this.pattern)}, ${JSON.stringify(this.options)})`;
}
}
Object.defineProperty(BSONRegExp.prototype, '_bsontype', { value: 'BSONRegExp' });

@@ -12,3 +12,9 @@ /** @public */

export class BSONSymbol {
_bsontype!: 'Symbol';
get _bsontype(): 'BSONSymbol' {
return 'BSONSymbol';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -20,4 +26,2 @@ value!: string;

constructor(value: string) {
if (!(this instanceof BSONSymbol)) return new BSONSymbol(value);
this.value = value;

@@ -59,3 +63,1 @@ }

}
Object.defineProperty(BSONSymbol.prototype, '_bsontype', { value: 'Symbol' });

@@ -0,3 +1,4 @@

import { BSONError } from './error';
import type { Int32 } from './int_32';
import { Long } from './long';
import { isObjectLike } from './parser/utils';

@@ -7,3 +8,7 @@ /** @public */

/** @public */
export type LongWithoutOverrides = new (low: unknown, high?: number, unsigned?: boolean) => {
export type LongWithoutOverrides = new (
low: unknown,
high?: number | boolean,
unsigned?: boolean
) => {
[P in Exclude<keyof Long, TimestampOverrides>]: Long[P];

@@ -28,3 +33,9 @@ };

export class Timestamp extends LongWithoutOverridesClass {
_bsontype!: 'Timestamp';
get _bsontype(): 'Timestamp' {
return 'Timestamp';
}
/** @internal */
get [Symbol.for('@@mdb.bson.version')](): 5 {
return 5;
}

@@ -34,4 +45,8 @@ static readonly MAX_VALUE = Long.MAX_UNSIGNED_VALUE;

/**
* @param low - A 64-bit Long representing the Timestamp.
* @param int - A 64-bit bigint representing the Timestamp.
*/
constructor(int: bigint);
/**
* @param long - A 64-bit Long representing the Timestamp.
*/
constructor(long: Long);

@@ -42,26 +57,39 @@ /**

constructor(value: { t: number; i: number });
/**
* @param low - the low (signed) 32 bits of the Timestamp.
* @param high - the high (signed) 32 bits of the Timestamp.
* @deprecated Please use `Timestamp({ t: high, i: low })` or `Timestamp(Long(low, high))` instead.
*/
constructor(low: number, high: number);
constructor(low: number | Long | { t: number; i: number }, high?: number) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
if (!(this instanceof Timestamp)) return new Timestamp(low, high);
constructor(low?: bigint | Long | { t: number | Int32; i: number | Int32 }) {
if (low == null) {
super(0, 0, true);
} else if (typeof low === 'bigint') {
super(low, true);
} else if (Long.isLong(low)) {
super(low.low, low.high, true);
} else if (typeof low === 'object' && 't' in low && 'i' in low) {
if (typeof low.t !== 'number' && (typeof low.t !== 'object' || low.t._bsontype !== 'Int32')) {
throw new BSONError('Timestamp constructed from { t, i } must provide t as a number');
}
if (typeof low.i !== 'number' && (typeof low.i !== 'object' || low.i._bsontype !== 'Int32')) {
throw new BSONError('Timestamp constructed from { t, i } must provide i as a number');
}
if (low.t < 0) {
throw new BSONError('Timestamp constructed from { t, i } must provide a positive t');
}
if (low.i < 0) {
throw new BSONError('Timestamp constructed from { t, i } must provide a positive i');
}
if (low.t > 0xffff_ffff) {
throw new BSONError(
'Timestamp constructed from { t, i } must provide t equal or less than uint32 max'
);
}
if (low.i > 0xffff_ffff) {
throw new BSONError(
'Timestamp constructed from { t, i } must provide i equal or less than uint32 max'
);
}
if (Long.isLong(low)) {
super(low.low, low.high, true);
} else if (isObjectLike(low) && typeof low.t !== 'undefined' && typeof low.i !== 'undefined') {
super(low.i, low.t, true);
super(low.i.valueOf(), low.t.valueOf(), true);
} else {
super(low, high, true);
throw new BSONError(
'A Timestamp can only be constructed with: bigint, Long, or { t: number; i: number }'
);
}
Object.defineProperty(this, '_bsontype', {
value: 'Timestamp',
writable: false,
configurable: false,
enumerable: false
});
}

@@ -92,3 +120,3 @@

static fromBits(lowBits: number, highBits: number): Timestamp {
return new Timestamp(lowBits, highBits);
return new Timestamp({ i: lowBits, t: highBits });
}

@@ -113,3 +141,10 @@

static fromExtendedJSON(doc: TimestampExtended): Timestamp {
return new Timestamp(doc.$timestamp);
// The Long check is necessary because extended JSON has different behavior given the size of the input number
const i = Long.isLong(doc.$timestamp.i)
? doc.$timestamp.i.getLowBitsUnsigned() // Need to fetch the least significant 32 bits
: doc.$timestamp.i;
const t = Long.isLong(doc.$timestamp.t)
? doc.$timestamp.t.getLowBitsUnsigned() // Need to fetch the least significant 32 bits
: doc.$timestamp.t;
return new Timestamp({ t, i });
}

@@ -116,0 +151,0 @@

@@ -1,3 +0,3 @@

import { Buffer } from 'buffer';
import { BSONTypeError } from './error';
import { ByteUtils } from './utils/byte_utils';

@@ -11,3 +11,3 @@ // Validation regex for v4 uuid (validates with or without dashes)

export const uuidHexStringToBuffer = (hexString: string): Buffer => {
export const uuidHexStringToBuffer = (hexString: string): Uint8Array => {
if (!uuidValidateString(hexString)) {

@@ -20,16 +20,16 @@ throw new BSONTypeError(

const sanitizedHexString = hexString.replace(/-/g, '');
return Buffer.from(sanitizedHexString, 'hex');
return ByteUtils.fromHex(sanitizedHexString);
};
export const bufferToUuidHexString = (buffer: Buffer, includeDashes = true): string =>
includeDashes
? buffer.toString('hex', 0, 4) +
'-' +
buffer.toString('hex', 4, 6) +
'-' +
buffer.toString('hex', 6, 8) +
'-' +
buffer.toString('hex', 8, 10) +
'-' +
buffer.toString('hex', 10, 16)
: buffer.toString('hex');
export function bufferToUuidHexString(buffer: Uint8Array, includeDashes = true): string {
if (includeDashes) {
return [
ByteUtils.toHex(buffer.subarray(0, 4)),
ByteUtils.toHex(buffer.subarray(4, 6)),
ByteUtils.toHex(buffer.subarray(6, 8)),
ByteUtils.toHex(buffer.subarray(8, 10)),
ByteUtils.toHex(buffer.subarray(10, 16))
].join('-');
}
return ByteUtils.toHex(buffer);
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc