Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(NODE-4867)!: adopt BSON v5 #3490

Merged
merged 18 commits into from
Jan 20, 2023
2 changes: 1 addition & 1 deletion etc/notes/CHANGES_5.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The following is a detailed collection of the changes in the major v5 release of

### Dot Notation Typescript Support Removed By Default

**NOTE** This is a **Typescript compile-time only** change. Dot notation in filters sent to MongoDB will still work the same.
**NOTE** This is a **Typescript compile-time only** change. Dot notation in filters sent to MongoDB will still work the same.

Version 4.3.0 introduced Typescript support for dot notation in filter predicates. For example:

Expand Down
55 changes: 39 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"email": "dbx-node@mongodb.com"
},
"dependencies": {
"bson": "^4.7.0",
"bson": "^5.0.0-alpha.3",
"mongodb-connection-string-url": "^2.6.0",
"socks": "^2.7.1"
},
Expand Down
11 changes: 3 additions & 8 deletions src/bson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import type { DeserializeOptions, SerializeOptions } from 'bson';

export {
Binary,
BSON,
BSONRegExp,
BSONSymbol,
BSONType,
calculateObjectSize,
Code,
DBRef,
Expand All @@ -13,21 +15,13 @@ export {
Double,
Int32,
Long,
Map,
MaxKey,
MinKey,
ObjectId,
serialize,
Timestamp
} from 'bson';

// TODO(NODE-4867): fix with bson v5
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-var-requires
const BSON = require('bson');

export { BSON };

/**
* BSON Serialization options.
* @public
Expand All @@ -42,6 +36,7 @@ export interface BSONSerializeOptions
| 'allowObjectSmallerThanBufferSize'
| 'index'
| 'validation'
| 'useBigInt64'
> {
/**
* Enabling the raw option will return a [Node.js Buffer](https://nodejs.org/api/buffer.html)
Expand Down
7 changes: 4 additions & 3 deletions src/cmap/auth/mongodb_aws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
MongoMissingCredentialsError,
MongoRuntimeError
} from '../../error';
import { Callback, maxWireVersion, ns } from '../../utils';
import { ByteUtils, Callback, maxWireVersion, ns } from '../../utils';
import { AuthContext, AuthProvider } from './auth_provider';
import { MongoCredentials } from './mongo_credentials';
import { AuthMechanism } from './providers';
Expand Down Expand Up @@ -108,7 +108,8 @@ export class MongoDBAWS extends AuthProvider {
return;
}

if (serverNonce.compare(nonce, 0, nonce.length, 0, nonce.length) !== 0) {
// TODO(NODE-4990)
if (!ByteUtils.equals(serverNonce.subarray(0, nonce.byteLength), nonce)) {
dariakp marked this conversation as resolved.
Show resolved Hide resolved
// TODO(NODE-3483)
callback(new MongoRuntimeError('Server nonce does not begin with client nonce'));
return;
Expand All @@ -130,7 +131,7 @@ export class MongoDBAWS extends AuthProvider {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': body.length,
'X-MongoDB-Server-Nonce': serverNonce.toString('base64'),
'X-MongoDB-Server-Nonce': ByteUtils.toBase64(serverNonce),
'X-MongoDB-GS2-CB-Flag': 'n'
},
path: '/',
Expand Down
6 changes: 3 additions & 3 deletions src/cmap/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class Query {
}

// Uses a single allocated buffer for the process, avoiding multiple memory allocations
toBin(): Buffer[] {
toBin(): Uint8Array[] {
const buffers = [];
let projection = null;

Expand Down Expand Up @@ -550,7 +550,7 @@ export class Msg {
return buffers;
}

makeDocumentSegment(buffers: Buffer[], document: Document): number {
makeDocumentSegment(buffers: Uint8Array[], document: Document): number {
const payloadTypeBuffer = Buffer.alloc(1);
payloadTypeBuffer[0] = 0;

Expand All @@ -561,7 +561,7 @@ export class Msg {
return payloadTypeBuffer.length + documentBuffer.length;
}

serializeBson(document: Document): Buffer {
serializeBson(document: Document): Uint8Array {
return BSON.serialize(document, {
checkKeys: this.checkKeys,
serializeFunctions: this.serializeFunctions,
Expand Down
5 changes: 2 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ import { MongoClient } from './mongo_client';
import { CancellationToken } from './mongo_types';
import { ClientSession } from './sessions';

/** @internal */
/** @public */
export { BSON } from './bson';
export {
Binary,
BSONRegExp,
BSONSymbol,
BSONType,
Code,
DBRef,
Decimal128,
Double,
Int32,
Long,
Map,
MaxKey,
MinKey,
ObjectId,
Expand Down Expand Up @@ -103,7 +103,6 @@ export { MongoErrorLabel } from './error';
export { ExplainVerbosity } from './explain';
export { LoggerLevel } from './logger';
export { ServerApiVersion } from './mongo_client';
export { BSONType } from './mongo_types';
export { ReturnDocument } from './operations/find_and_modify';
export { ProfilingLevel } from './operations/set_profiling_level';
export { ReadConcernLevel } from './read_concern';
Expand Down
29 changes: 1 addition & 28 deletions src/mongo_types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ObjectIdLike } from 'bson';
import type { BSONType, ObjectIdLike } from 'bson';
import { EventEmitter } from 'events';

import type {
Expand Down Expand Up @@ -158,33 +158,6 @@ export type BitwiseFilter =
| Binary /** BinData bit mask */
| ReadonlyArray<number>; /** `[ <position1>, <position2>, ... ]` */

/** @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];
/** @public */
export type BSONTypeAlias = keyof typeof BSONType;

Expand Down
3 changes: 2 additions & 1 deletion src/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { ReadPreference } from './read_preference';
import { _advanceClusterTime, ClusterTime, TopologyType } from './sdam/common';
import { isTransactionCommand, Transaction, TransactionOptions, TxnState } from './transactions';
import {
ByteUtils,
calculateDurationInMs,
Callback,
commandSupportsReadConcern,
Expand Down Expand Up @@ -347,7 +348,7 @@ export class ClientSession extends TypedEventEmitter<ClientSessionEvents> {
return false;
}

return this.id.id.buffer.equals(session.id.id.buffer);
return ByteUtils.equals(this.id.id.buffer, session.id.id.buffer);
}

/**
Expand Down
24 changes: 21 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,28 @@ import { W, WriteConcern, WriteConcernOptions } from './write_concern';
*/
export type Callback<T = any> = (error?: AnyError, result?: T) => void;

export const MAX_JS_INT = Number.MAX_SAFE_INTEGER + 1;

export type AnyOptions = Document;

export const ByteUtils = {
toLocalBufferType(this: void, buffer: Buffer | Uint8Array): Buffer {
return Buffer.isBuffer(buffer)
? buffer
: Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength);
},

equals(this: void, seqA: Uint8Array, seqB: Uint8Array) {
return ByteUtils.toLocalBufferType(seqA).equals(seqB);
},

compare(this: void, seqA: Uint8Array, seqB: Uint8Array) {
return ByteUtils.toLocalBufferType(seqA).compare(seqB);
},

toBase64(this: void, uint8array: Uint8Array) {
return ByteUtils.toLocalBufferType(uint8array).toString('base64');
}
};

/**
* Throws if collectionName is not a valid mongodb collection namespace.
* @internal
Expand Down Expand Up @@ -1401,7 +1419,7 @@ export function compareObjectId(oid1?: ObjectId | null, oid2?: ObjectId | null):
return 1;
}

return oid1.id.compare(oid2.id);
return ByteUtils.compare(oid1.id, oid2.id);
}

export function parseInteger(value: unknown): number | null {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ describe('Change Stream prose tests', function () {

// Helpers
timestamp() {
return new Timestamp(this._timestampCounter++, Date.now());
return new Timestamp({ i: this._timestampCounter++, t: this._timestampCounter });
}

applyOpTime(obj) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@ const skippedAuthTests = [
'unset works with an encrypted field',
'updateOne with deterministic encryption',
'updateMany with deterministic encryption',
'type=date',
'type=regex',
'type=timestamp',
'type=javascript',
'type=binData',
'type=int',
'type=objectId',
'type=symbol',
dariakp marked this conversation as resolved.
Show resolved Hide resolved
'replaceOne with encryption',
'Insert with encryption on a missing key',
'A local schema should override',
Expand Down
Loading