Comparing version 6.13.1 to 6.14.0
@@ -106,2 +106,3 @@ "use strict"; | ||
const mongoCryptOptions = { | ||
enableMultipleCollinfo: true, | ||
cryptoCallbacks | ||
@@ -108,0 +109,0 @@ }; |
@@ -98,6 +98,13 @@ "use strict"; | ||
let result = null; | ||
while (context.state !== MONGOCRYPT_CTX_DONE && context.state !== MONGOCRYPT_CTX_ERROR) { | ||
// Typescript treats getters just like properties: Once you've tested it for equality | ||
// it cannot change. Which is exactly the opposite of what we use state and status for. | ||
// Every call to at least `addMongoOperationResponse` and `finalize` can change the state. | ||
// These wrappers let us write code more naturally and not add compiler exceptions | ||
// to conditions checks inside the state machine. | ||
const getStatus = () => context.status; | ||
const getState = () => context.state; | ||
while (getState() !== MONGOCRYPT_CTX_DONE && getState() !== MONGOCRYPT_CTX_ERROR) { | ||
options.signal?.throwIfAborted(); | ||
debug(`[context#${context.id}] ${stateToString.get(context.state) || context.state}`); | ||
switch (context.state) { | ||
debug(`[context#${context.id}] ${stateToString.get(getState()) || getState()}`); | ||
switch (getState()) { | ||
case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: { | ||
@@ -108,6 +115,10 @@ const filter = (0, bson_1.deserialize)(context.nextMongoOperation()); | ||
} | ||
const collInfo = await this.fetchCollectionInfo(metaDataClient, context.ns, filter, options); | ||
if (collInfo) { | ||
context.addMongoOperationResponse(collInfo); | ||
const collInfoCursor = this.fetchCollectionInfo(metaDataClient, context.ns, filter, options); | ||
for await (const collInfo of collInfoCursor) { | ||
context.addMongoOperationResponse((0, bson_1.serialize)(collInfo)); | ||
if (getState() === MONGOCRYPT_CTX_ERROR) | ||
break; | ||
} | ||
if (getState() === MONGOCRYPT_CTX_ERROR) | ||
break; | ||
context.finishMongoOperation(); | ||
@@ -118,2 +129,4 @@ break; | ||
const command = context.nextMongoOperation(); | ||
if (getState() === MONGOCRYPT_CTX_ERROR) | ||
break; | ||
if (!mongocryptdClient) { | ||
@@ -155,5 +168,4 @@ throw new errors_1.MongoCryptError('unreachable state machine state: entered MONGOCRYPT_CTX_NEED_MONGO_MARKINGS but mongocryptdClient is undefined'); | ||
const finalizedContext = context.finalize(); | ||
// @ts-expect-error finalize can change the state, check for error | ||
if (context.state === MONGOCRYPT_CTX_ERROR) { | ||
const message = context.status.message || 'Finalization error'; | ||
if (getState() === MONGOCRYPT_CTX_ERROR) { | ||
const message = getStatus().message || 'Finalization error'; | ||
throw new errors_1.MongoCryptError(message); | ||
@@ -165,7 +177,7 @@ } | ||
default: | ||
throw new errors_1.MongoCryptError(`Unknown state: ${context.state}`); | ||
throw new errors_1.MongoCryptError(`Unknown state: ${getState()}`); | ||
} | ||
} | ||
if (context.state === MONGOCRYPT_CTX_ERROR || result == null) { | ||
const message = context.status.message; | ||
if (getState() === MONGOCRYPT_CTX_ERROR || result == null) { | ||
const message = getStatus().message; | ||
if (!message) { | ||
@@ -351,3 +363,3 @@ debug(`unidentifiable error in MongoCrypt - received an error status from \`libmongocrypt\` but received no error message.`); | ||
*/ | ||
async fetchCollectionInfo(client, ns, filter, options) { | ||
fetchCollectionInfo(client, ns, filter, options) { | ||
const { db } = utils_1.MongoDBCollectionNamespace.fromString(ns); | ||
@@ -358,10 +370,6 @@ const cursor = client.db(db).listCollections(filter, { | ||
timeoutContext: options?.timeoutContext && new abstract_cursor_1.CursorTimeoutContext(options?.timeoutContext, Symbol()), | ||
signal: options?.signal | ||
signal: options?.signal, | ||
nameOnly: false | ||
}); | ||
// There is always exactly zero or one matching documents, so this should always exhaust the cursor | ||
// in a single batch. We call `toArray()` just to be safe and ensure that the cursor is always | ||
// exhausted and closed. | ||
const collections = await cursor.toArray(); | ||
const info = collections.length > 0 ? (0, bson_1.serialize)(collections[0]) : null; | ||
return info; | ||
return cursor; | ||
} | ||
@@ -368,0 +376,0 @@ /** |
@@ -9,3 +9,2 @@ "use strict"; | ||
const util_1 = require("util"); | ||
const types_1 = require("util/types"); | ||
const bson_1 = require("./bson"); | ||
@@ -168,3 +167,3 @@ const constants_1 = require("./constants"); | ||
case 'object': | ||
if ((0, types_1.isUint8Array)(value)) { | ||
if ((0, utils_1.isUint8Array)(value)) { | ||
// '{"$binary":{"base64":"<base64 string>","subType":"XX"}}' | ||
@@ -171,0 +170,0 @@ // This is an estimate based on the fact that the base64 is approximately 1.33x the length of |
{ | ||
"name": "mongodb", | ||
"version": "6.13.1", | ||
"version": "6.14.0", | ||
"description": "The official MongoDB driver for Node.js", | ||
@@ -33,3 +33,3 @@ "main": "lib/index.js", | ||
"peerDependencies": { | ||
"@aws-sdk/credential-providers": "^3.632.0", | ||
"@aws-sdk/credential-providers": "^3.188.0", | ||
"@mongodb-js/zstd": "^1.1.0 || ^2.0.0", | ||
@@ -100,3 +100,3 @@ "gcp-metadata": "^5.2.0", | ||
"mocha-sinon": "^2.1.2", | ||
"mongodb-client-encryption": "^6.2.0", | ||
"mongodb-client-encryption": "^6.3.0", | ||
"mongodb-legacy": "^6.1.3", | ||
@@ -103,0 +103,0 @@ "nyc": "^15.1.0", |
@@ -422,2 +422,9 @@ import type { Readable } from 'stream'; | ||
operationType: 'create'; | ||
/** | ||
* The type of the newly created object. | ||
* | ||
* @sinceServerVersion 8.1.0 | ||
*/ | ||
nsType?: 'collection' | 'timeseries' | 'view'; | ||
} | ||
@@ -424,0 +431,0 @@ |
@@ -242,2 +242,3 @@ import { | ||
const mongoCryptOptions: MongoCryptOptions = { | ||
enableMultipleCollinfo: true, | ||
cryptoCallbacks | ||
@@ -244,0 +245,0 @@ }; |
@@ -19,2 +19,3 @@ import * as fs from 'fs/promises'; | ||
import { type Abortable } from '../mongo_types'; | ||
import { type CollectionInfo } from '../operations/list_collections'; | ||
import { Timeout, type TimeoutContext, TimeoutError } from '../timeout'; | ||
@@ -209,7 +210,15 @@ import { | ||
while (context.state !== MONGOCRYPT_CTX_DONE && context.state !== MONGOCRYPT_CTX_ERROR) { | ||
// Typescript treats getters just like properties: Once you've tested it for equality | ||
// it cannot change. Which is exactly the opposite of what we use state and status for. | ||
// Every call to at least `addMongoOperationResponse` and `finalize` can change the state. | ||
// These wrappers let us write code more naturally and not add compiler exceptions | ||
// to conditions checks inside the state machine. | ||
const getStatus = () => context.status; | ||
const getState = () => context.state; | ||
while (getState() !== MONGOCRYPT_CTX_DONE && getState() !== MONGOCRYPT_CTX_ERROR) { | ||
options.signal?.throwIfAborted(); | ||
debug(`[context#${context.id}] ${stateToString.get(context.state) || context.state}`); | ||
debug(`[context#${context.id}] ${stateToString.get(getState()) || getState()}`); | ||
switch (context.state) { | ||
switch (getState()) { | ||
case MONGOCRYPT_CTX_NEED_MONGO_COLLINFO: { | ||
@@ -223,3 +232,3 @@ const filter = deserialize(context.nextMongoOperation()); | ||
const collInfo = await this.fetchCollectionInfo( | ||
const collInfoCursor = this.fetchCollectionInfo( | ||
metaDataClient, | ||
@@ -230,6 +239,10 @@ context.ns, | ||
); | ||
if (collInfo) { | ||
context.addMongoOperationResponse(collInfo); | ||
for await (const collInfo of collInfoCursor) { | ||
context.addMongoOperationResponse(serialize(collInfo)); | ||
if (getState() === MONGOCRYPT_CTX_ERROR) break; | ||
} | ||
if (getState() === MONGOCRYPT_CTX_ERROR) break; | ||
context.finishMongoOperation(); | ||
@@ -241,2 +254,4 @@ break; | ||
const command = context.nextMongoOperation(); | ||
if (getState() === MONGOCRYPT_CTX_ERROR) break; | ||
if (!mongocryptdClient) { | ||
@@ -291,5 +306,4 @@ throw new MongoCryptError( | ||
const finalizedContext = context.finalize(); | ||
// @ts-expect-error finalize can change the state, check for error | ||
if (context.state === MONGOCRYPT_CTX_ERROR) { | ||
const message = context.status.message || 'Finalization error'; | ||
if (getState() === MONGOCRYPT_CTX_ERROR) { | ||
const message = getStatus().message || 'Finalization error'; | ||
throw new MongoCryptError(message); | ||
@@ -302,8 +316,8 @@ } | ||
default: | ||
throw new MongoCryptError(`Unknown state: ${context.state}`); | ||
throw new MongoCryptError(`Unknown state: ${getState()}`); | ||
} | ||
} | ||
if (context.state === MONGOCRYPT_CTX_ERROR || result == null) { | ||
const message = context.status.message; | ||
if (getState() === MONGOCRYPT_CTX_ERROR || result == null) { | ||
const message = getStatus().message; | ||
if (!message) { | ||
@@ -537,3 +551,3 @@ debug( | ||
*/ | ||
async fetchCollectionInfo( | ||
fetchCollectionInfo( | ||
client: MongoClient, | ||
@@ -543,3 +557,3 @@ ns: string, | ||
options?: { timeoutContext?: TimeoutContext } & Abortable | ||
): Promise<Uint8Array | null> { | ||
): AsyncIterable<CollectionInfo> { | ||
const { db } = MongoDBCollectionNamespace.fromString(ns); | ||
@@ -552,12 +566,7 @@ | ||
options?.timeoutContext && new CursorTimeoutContext(options?.timeoutContext, Symbol()), | ||
signal: options?.signal | ||
signal: options?.signal, | ||
nameOnly: false | ||
}); | ||
// There is always exactly zero or one matching documents, so this should always exhaust the cursor | ||
// in a single batch. We call `toArray()` just to be safe and ensure that the cursor is always | ||
// exhausted and closed. | ||
const collections = await cursor.toArray(); | ||
const info = collections.length > 0 ? serialize(collections[0]) : null; | ||
return info; | ||
return cursor; | ||
} | ||
@@ -564,0 +573,0 @@ |
@@ -969,4 +969,12 @@ import { type BSONSerializeOptions, type Document, resolveBSONOptions } from './bson'; | ||
* | ||
* The value of `update` can be either: | ||
* - UpdateFilter<TSchema> - A document that contains update operator expressions, | ||
* - Document[] - an aggregation pipeline consisting of the following stages: | ||
* - $addFields and its alias $set | ||
* - $project and its alias $unset | ||
* - $replaceRoot and its alias $replaceWith. | ||
* See the [findAndModify command documentation](https://www.mongodb.com/docs/manual/reference/command/findAndModify) for details. | ||
* | ||
* @param filter - The filter used to select the document to update | ||
* @param update - Update operations to be performed on the document | ||
* @param update - The modifications to apply | ||
* @param options - Optional settings for the command | ||
@@ -976,3 +984,3 @@ */ | ||
filter: Filter<TSchema>, | ||
update: UpdateFilter<TSchema>, | ||
update: UpdateFilter<TSchema> | Document[], | ||
options: FindOneAndUpdateOptions & { includeResultMetadata: true } | ||
@@ -982,3 +990,3 @@ ): Promise<ModifyResult<TSchema>>; | ||
filter: Filter<TSchema>, | ||
update: UpdateFilter<TSchema>, | ||
update: UpdateFilter<TSchema> | Document[], | ||
options: FindOneAndUpdateOptions & { includeResultMetadata: false } | ||
@@ -988,3 +996,3 @@ ): Promise<WithId<TSchema> | null>; | ||
filter: Filter<TSchema>, | ||
update: UpdateFilter<TSchema>, | ||
update: UpdateFilter<TSchema> | Document[], | ||
options: FindOneAndUpdateOptions | ||
@@ -994,7 +1002,7 @@ ): Promise<WithId<TSchema> | null>; | ||
filter: Filter<TSchema>, | ||
update: UpdateFilter<TSchema> | ||
update: UpdateFilter<TSchema> | Document[] | ||
): Promise<WithId<TSchema> | null>; | ||
async findOneAndUpdate( | ||
filter: Filter<TSchema>, | ||
update: UpdateFilter<TSchema>, | ||
update: UpdateFilter<TSchema> | Document[], | ||
options?: FindOneAndUpdateOptions | ||
@@ -1001,0 +1009,0 @@ ): Promise<WithId<TSchema> | ModifyResult<TSchema> | null> { |
import { inspect, promisify } from 'util'; | ||
import { isUint8Array } from 'util/types'; | ||
@@ -78,3 +77,3 @@ import { | ||
} from './sdam/server_selection_events'; | ||
import { HostAddress, isPromiseLike, parseUnsignedInteger } from './utils'; | ||
import { HostAddress, isPromiseLike, isUint8Array, parseUnsignedInteger } from './utils'; | ||
@@ -81,0 +80,0 @@ /** |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
3771427
78613