diff --git a/APIReference.md b/APIReference.md
index 5e4e72b..9d77b95 100644
--- a/APIReference.md
+++ b/APIReference.md
@@ -632,7 +632,7 @@ for tables and CollectionsDb class for collections.
**Kind**: global class
* [BaseDb](#BaseDb)
- * [new BaseDb()](#new_BaseDb_new)
+ * [.isTable](#BaseDb+isTable)
* [.createTable(name, definition)](#BaseDb+createTable)
* [.dropCollection(name)](#BaseDb+dropCollection)
* [.dropTable(name)](#BaseDb+dropTable)
@@ -645,13 +645,14 @@ for tables and CollectionsDb class for collections.
* [.syncTypes(types)](#BaseDb+syncTypes) ⇒
* [.command(command)](#BaseDb+command)
-
+
-### new BaseDb()
+### baseDb.isTable
Whether we're using "tables mode" or "collections mode". If tables mode, then collection() returns
a Table instance, not a Collection instance. Also, if tables mode, createCollection() throws an
error for Mongoose syncIndexes() compatibility reasons.
+**Kind**: instance property of [BaseDb](#BaseDb)
### baseDb.createTable(name, definition)
@@ -1033,7 +1034,7 @@ the one exception being strings.
**Extends**: [BaseDb](#BaseDb)
* [BaseDb](#BaseDb) ⇐ [BaseDb](#BaseDb)
- * [new BaseDb()](#new_BaseDb_new)
+ * [.isTable](#BaseDb+isTable)
* [.createTable(name, definition)](#BaseDb+createTable)
* [.dropCollection(name)](#BaseDb+dropCollection)
* [.dropTable(name)](#BaseDb+dropTable)
@@ -1046,13 +1047,14 @@ the one exception being strings.
* [.syncTypes(types)](#BaseDb+syncTypes) ⇒
* [.command(command)](#BaseDb+command)
-
+
-### new BaseDb()
+### baseDb.isTable
Whether we're using "tables mode" or "collections mode". If tables mode, then collection() returns
a Table instance, not a Collection instance. Also, if tables mode, createCollection() throws an
error for Mongoose syncIndexes() compatibility reasons.
+**Kind**: instance property of [BaseDb](#BaseDb)
### baseDb.createTable(name, definition)
diff --git a/bin/warm-up-tests.ts b/bin/warm-up-tests.ts
index 1a0943a..9450d47 100644
--- a/bin/warm-up-tests.ts
+++ b/bin/warm-up-tests.ts
@@ -57,7 +57,7 @@ async function main() {
}
}
- const collection = connection.db!.collection(collectionName, {});
+ const collection = connection.astraDb!.collection(collectionName, {});
await retryNotEnoughReplicas(async () => {
await collection.insertOne({ ping: true, ts: new Date() });
await collection.deleteMany({});
diff --git a/jsdoc2md.json b/jsdoc2md.json
index 6a8f81e..ea0244b 100644
--- a/jsdoc2md.json
+++ b/jsdoc2md.json
@@ -8,6 +8,6 @@
"extensions": ["ts", "tsx"],
"ignore": ["**/*.(test|spec).ts"],
"babelrc": false,
- "presets": [["@babel/preset-env", { "targets": { "node": true } }], "@babel/preset-typescript"]
+ "presets": [["@babel/preset-env", { "targets": { "node": true } }], ["@babel/preset-typescript", { "allowDeclareFields": true }]]
}
}
diff --git a/src/driver/collection.ts b/src/driver/collection.ts
index 7bc65eb..1493c3c 100644
--- a/src/driver/collection.ts
+++ b/src/driver/collection.ts
@@ -63,7 +63,7 @@ import { OperationNotSupportedError } from '../operationNotSupportedError';
import { SchemaOptions } from 'mongoose';
import { Writable } from 'stream';
import deserializeDoc from '../deserializeDoc';
-import { IndexSpecification, Sort as MongoDBSort, WithId, InferIdType } from 'mongodb';
+import { FindCursor, IndexSpecification, ListIndexesCursor, Sort as MongoDBSort, WithId, InferIdType } from 'mongodb';
import { inspect } from 'util';
import { serialize } from '../serialize';
import { setDefaultIdForUpdate, setDefaultIdForReplace } from '../setDefaultIdForUpsert';
@@ -77,7 +77,7 @@ type FindOptions = (Omit | Omit | Omit)
& { sort?: MongooseSortOption, maxTimeMS?: number, timeout?: boolean };
-type FindOneAndUpdateOptions = Omit
+type FindOneAndUpdateOptions = Omit
& { sort?: MongooseSortOption, includeResultMetadata?: boolean };
type FindOneAndDeleteOptions = Omit
& { sort?: MongooseSortOption, includeResultMetadata?: boolean, maxTimeMS?: number };
@@ -90,15 +90,6 @@ type ReplaceOneOptions = Omit
type UpdateOneOptions = (Omit | Omit)
& { sort?: MongooseSortOption, maxTimeMS?: number };
-interface AstraMongooseIndexDescription {
- name: string,
- definition: {
- column: string | ({ [key: string]: '$keys' | '$values' }),
- options?: TableIndexOptions | TableVectorIndexOptions | TableTextIndexOptions;
- },
- key: Record
-}
-
interface AstraIndexDescription {
name: string;
definition: {
@@ -128,8 +119,7 @@ export class Collection = Record | AstraTable;
_closed: boolean;
connection: Connection;
- // @ts-expect-error options is technically a function on Mongoose collections
- options?: (TableOptions | CollectionOptions) & MongooseCollectionOptions;
+ _options?: (TableOptions | CollectionOptions) & MongooseCollectionOptions;
name: string;
constructor(name: string, conn: Connection, options?: (TableOptions | CollectionOptions) & MongooseCollectionOptions) {
@@ -138,7 +128,7 @@ export class Collection = Record = Record` method below doesn't know whether we're creating a
// Astra Table or Astra Collection until runtime
- ? { serdes: this.options.schemaUserProvidedOptions.serdes } as unknown as Record
+ ? { serdes: this._options.schemaUserProvidedOptions.serdes } as unknown as Record
: {};
// Cache because @datastax/astra-db-ts doesn't
- const collection = this.connection.db!.collection(this.name, collectionOptions);
+ const collection = this.connection.astraDb!.collection(this.name, collectionOptions);
this._collection = collection;
// Bubble up collection-level events from astra-db-ts to the main connection
@@ -166,11 +156,11 @@ export class Collection = Record = Record = Record deserializeDoc(doc) as DocType);
+ return this.collection
+ .find(filter, requestOptions)
+ .map(doc => deserializeDoc(doc) as DocType) as unknown as FindCursor>;
}
/**
@@ -268,12 +259,12 @@ export class Collection = Record | Record[],
- options: FindOneAndUpdateOptions
- ) {
+ update: CollectionUpdateFilter | TableUpdateFilter | Record[],
+ options?: FindOneAndUpdateOptions
+ ): Promise {
+ options = options ?? {};
if (Array.isArray(update)) {
throw new AstraMongooseError('Astra-mongoose does not support update pipelines', { update });
}
@@ -289,10 +280,10 @@ export class Collection = Record(filter, update, requestOptions);
- update = serialize(update);
+ update = serialize(update as Record);
return await this.collection.findOneAndUpdate(filter, update, requestOptions).then((value: Record | null) => {
- if (options?.includeResultMetadata) {
+ if (options.includeResultMetadata) {
return { value: deserializeDoc(value) };
}
return deserializeDoc(value);
@@ -486,7 +477,7 @@ export class Collection = Record, requestOptions);
}
- update = serialize(update, this.isTable);
+ update = serialize(update as Record, this.isTable);
return await this.collection.updateOne(filter as TableFilter, update, requestOptions).then(res => {
// Mongoose currently has a bug where null response from updateOne() throws an error that we can't
// catch here for unknown reasons. See Automattic/mongoose#15126. Tables API returns null here.
@@ -503,8 +494,11 @@ export class Collection = Record | Record[], options: CollectionUpdateManyOptions) {
+ async updateMany(
+ filter: Filter,
+ update: CollectionUpdateFilter | TableUpdateFilter | Record[],
+ options?: Omit
+ ): Promise {
if (Array.isArray(update)) {
throw new AstraMongooseError('Astra-mongoose does not support update pipelines', { update });
}
@@ -514,10 +508,13 @@ export class Collection = Record ({ ...res, acknowledged: true }));
+ update = serialize(update as Record, this.isTable);
+ return await this.collection
+ .updateMany(filter, update, options)
+ .then(res => ({ ...res, acknowledged: true }));
}
/**
@@ -617,7 +614,7 @@ export class Collection = Record, options?: Omit) {
// eslint-disable-next-line prefer-rest-params
_logFunctionCall(this, this.connection.debug, this.name, 'runCommand', arguments);
- return await this.connection.db!.astraDb.command(
+ return await this.connection.astraDb!.astraDb.command(
command,
this.isTable ? { table: this.name, ...options } : { collection: this.name, ...options }
);
@@ -650,8 +647,7 @@ export class Collection = Record Promise } {
+ listIndexes(): ListIndexesCursor {
// eslint-disable-next-line prefer-rest-params
_logFunctionCall(this, this.connection.debug, this.name, 'listIndexes', arguments);
if (this.collection instanceof AstraCollection) {
@@ -669,7 +665,7 @@ export class Collection = Record ({ ...index, key: typeof index.definition.column === 'string' ? { [index.definition.column]: 1 } : index.definition.column }));
})
- };
+ } as unknown as ListIndexesCursor;
}
/**
@@ -734,7 +730,7 @@ export class Collection = Record | null = null;
client: DataAPIClient | null = null;
admin: AstraDbAdmin | DataAPIDbAdmin | null = null;
- // @ts-expect-error astra-mongoose Db classes don't fully extend from Mongoose Db in a TypeScript-compatible way.
- db: CollectionsDb | TablesDb | null = null;
+ declare db: undefined;
+ astraDb: CollectionsDb | TablesDb | undefined;
keyspaceName: string | null = null;
- config?: Partial;
+ config: Partial = {};
baseUrl: string | null = null;
baseApiPath: string | null = null;
models: Record> = {};
- // @ts-expect-error astra-mongoose collection currently doesn't fully extend from Mongoose collection in a TypeScript-compatible way.
collections: Record = {};
_debug?: boolean | { color?: boolean, shell?: boolean } | Writable | ((name: string, fn: string, ...args: unknown[]) => void) | null | undefined;
_connectionString: string | null = null;
@@ -147,7 +147,7 @@ export class Connection extends MongooseConnection {
// @ts-expect-error _waitForConnect not part of public API
await this._waitForConnect();
// Cannot happen, but this helps TypeScript infer the correct return type
- const db = this.db;
+ const db = this.astraDb;
const admin = this.admin;
assert.ok(db);
assert.ok(admin);
@@ -157,7 +157,7 @@ export class Connection extends MongooseConnection {
}
// Cannot happen, but this helps TypeScript infer the correct return type
- const db = this.db;
+ const db = this.astraDb;
const admin = this.admin;
assert.ok(db);
assert.ok(admin);
@@ -170,7 +170,6 @@ export class Connection extends MongooseConnection {
* @param options
*/
- // @ts-expect-error astra-mongoose collection currently doesn't fully extend from Mongoose collection in a TypeScript-compatible way.
collection = Record>(name: string, options?: MongooseCollectionOptions): Collection {
if (!(name in this.collections)) {
// @ts-expect-error astra-mongoose collection currently doesn't fully extend from Mongoose collection in a TypeScript-compatible way.
@@ -186,11 +185,10 @@ export class Connection extends MongooseConnection {
* @param name The keyspace name
* @param options
*/
- // @ts-expect-error astra-mongoose connection currently doesn't fully extend from Mongoose connection in a TypeScript-compatible way because of collections
useDb(name: string, options?: UseDbOptions): Connection {
options = options ?? {};
if (options.useCache && this.relatedDbs[name]) {
- const cachedDb = this.relatedDbs[name].db;
+ const cachedDb = this.relatedDbs[name].astraDb;
if (options?.isTable != null && cachedDb != null && options.isTable !== cachedDb.isTable) {
throw new AstraMongooseError(`Cannot use cached connection for ${name} with isTable=${options.isTable} (cached connection is isTable=${cachedDb.isTable})`);
}
@@ -222,7 +220,7 @@ export class Connection extends MongooseConnection {
const wireup = () => {
const client = this.client;
- const parentDb = this.db;
+ const parentDb = this.astraDb;
const admin = this.admin;
const baseUrl = this.baseUrl;
assert.ok(client);
@@ -249,7 +247,7 @@ export class Connection extends MongooseConnection {
});
this.initialConnection?.catch(err => rejectInitialConnection?.(err));
- if (this.db) {
+ if (this.astraDb) {
wireup();
} else {
// @ts-expect-error _queue is an internal Mongoose property.
@@ -273,13 +271,12 @@ export class Connection extends MongooseConnection {
* @param options
*/
- // @ts-expect-error astra-mongoose collection currently doesn't fully extend from Mongoose collection in a TypeScript-compatible way.
async createCollection = Record>(
name: string,
- options?: CreateCollectionOptions
- ) {
+ options?: MongoCreateCollectionOptions
+ ): Promise> {
const { db } = await this._waitForClient();
- return await db.createCollection(name, options);
+ return await db.createCollection(name, options as unknown as CreateCollectionOptions) as unknown as MongoDBCollection;
}
/**
@@ -461,7 +458,6 @@ export class Connection extends MongooseConnection {
* @param options
*/
- // @ts-expect-error astra-mongoose connection currently doesn't fully extend from Mongoose connection in a TypeScript-compatible way because of collections
async openUri(uri: string, options?: ConnectOptionsInternal) {
let _fireAndForget: boolean | undefined = false;
if (options && '_fireAndForget' in options) {
@@ -607,7 +603,7 @@ export class Connection extends MongooseConnection {
collection._collection = undefined;
}
- this.db = db;
+ this.astraDb = db;
this.admin = admin;
// Bubble up db-level events from astra-db-ts to the main connection.
@@ -624,8 +620,8 @@ export class Connection extends MongooseConnection {
}
_clearDbEventListeners() {
- if (this.db && this._dbEventListeners) {
- const dbEmitter = this.db.astraDb;
+ if (this.astraDb && this._dbEventListeners) {
+ const dbEmitter = this.astraDb.astraDb;
dbEmitter.off('commandStarted', this._dbEventListeners.commandStarted);
dbEmitter.off('commandFailed', this._dbEventListeners.commandFailed);
dbEmitter.off('commandSucceeded', this._dbEventListeners.commandSucceeded);
@@ -645,8 +641,8 @@ export class Connection extends MongooseConnection {
*/
async doClose() {
// Remove db-level event listeners if present
- if (this.db && this._dbEventListeners) {
- const dbEmitter = this.db.astraDb;
+ if (this.astraDb && this._dbEventListeners) {
+ const dbEmitter = this.astraDb.astraDb;
dbEmitter.off('commandStarted', this._dbEventListeners.commandStarted);
dbEmitter.off('commandFailed', this._dbEventListeners.commandFailed);
dbEmitter.off('commandSucceeded', this._dbEventListeners.commandSucceeded);
diff --git a/tests/driver/collections.api.test.ts b/tests/driver/collections.api.test.ts
index b95df77..9b76414 100644
--- a/tests/driver/collections.api.test.ts
+++ b/tests/driver/collections.api.test.ts
@@ -240,7 +240,7 @@ describe('COLLECTIONS: mongoose Model API level tests with collections', async (
let collections = await Product.db.listCollections().then(collections => collections.map(coll => coll.name));
assert.ok(collections.includes(Product.collection.collectionName));
- await Product.db.db!.dropCollection(Product.collection.collectionName);
+ await (Product.db as unknown as AstraMongooseDriver.Connection).astraDb!.dropCollection(Product.collection.collectionName);
collections = await Product.db.listCollections().then(collections => collections.map(coll => coll.name));
assert.ok(!collections.includes(Product.collection.collectionName));
@@ -315,7 +315,7 @@ describe('COLLECTIONS: mongoose Model API level tests with collections', async (
it('API ops tests Model.db', async () => {
const conn = Product.db as unknown as AstraMongooseDriver.Connection;
assert.strictEqual(conn.keyspaceName, parseUri(testClient!.uri).keyspaceName);
- assert.strictEqual(conn.db!.name, parseUri(testClient!.uri).keyspaceName);
+ assert.strictEqual(conn.astraDb!.name, parseUri(testClient!.uri).keyspaceName);
});
it('API ops tests Model.deleteMany()', async function() {
const product1 = new Product({name: 'Product 1', price: 10, isCertified: true, category: 'cat 1'});
@@ -874,7 +874,7 @@ describe('COLLECTIONS: mongoose Model API level tests with collections', async (
const { keyspaceName } = parseUri(testClient!.uri);
const childConnection = connection.useDb(keyspaceName, { isTable: true });
- assert.strictEqual(childConnection.db!.isTable, true);
+ assert.strictEqual(childConnection.astraDb!.isTable, true);
await assert.rejects(
childConnection.createCollection('use_db_is_table_child'),
/Cannot createCollection in tables mode/
@@ -888,7 +888,7 @@ describe('COLLECTIONS: mongoose Model API level tests with collections', async (
const { keyspaceName } = parseUri(testClient!.uri);
const childConnection = connection.useDb(keyspaceName, { useCache: true, isTable: true });
- assert.strictEqual(childConnection.db!.isTable, true);
+ assert.strictEqual(childConnection.astraDb!.isTable, true);
assert.strictEqual(connection.useDb(keyspaceName, { useCache: true, isTable: true }), childConnection);
assert.throws(
() => connection.useDb(keyspaceName, { useCache: true, isTable: false }),
@@ -909,7 +909,7 @@ describe('COLLECTIONS: mongoose Model API level tests with collections', async (
await childConnection.asPromise();
assert.strictEqual(childConnection.client, connection.client);
- assert.notStrictEqual(childConnection.db, connection.db);
+ assert.notStrictEqual(childConnection.astraDb, connection.astraDb);
assert.strictEqual(childConnection.keyspaceName, keyspaceName);
assert.ok((await promise.then(res => res.map(obj => obj.name))).includes(Product.collection.collectionName));
@@ -923,7 +923,7 @@ describe('COLLECTIONS: mongoose Model API level tests with collections', async (
await connection.openUri(testClient!.uri, testClient!.options);
await childConnection.asPromise();
- assert.strictEqual(childConnection.db!.isTable, true);
+ assert.strictEqual(childConnection.astraDb!.isTable, true);
await assert.rejects(
childConnection.createCollection('use_db_is_table_child'),
/Cannot createCollection in tables mode/
diff --git a/tests/driver/collections.driver.test.ts b/tests/driver/collections.driver.test.ts
index 4e1999f..80bcad8 100644
--- a/tests/driver/collections.driver.test.ts
+++ b/tests/driver/collections.driver.test.ts
@@ -226,7 +226,7 @@ describe('COLLECTIONS: driver based tests', async () => {
}
const _id = new mongoose.Types.ObjectId();
- const collection = mongooseInstance.connection.db!.collection(
+ const collection = mongooseInstance.connection.astraDb!.collection(
Product.collection.collectionName,
{ serdes: { enableBigNumbers: () => 'number_or_string' } }
);
diff --git a/tests/driver/tables.api.test.ts b/tests/driver/tables.api.test.ts
index bc38aed..ceb847b 100644
--- a/tests/driver/tables.api.test.ts
+++ b/tests/driver/tables.api.test.ts
@@ -206,7 +206,7 @@ describe('TABLES: Mongoose Model API level tests', async () => {
it('API ops tests Model.db', async () => {
const conn = Product.db as unknown as AstraMongooseDriver.Connection;
assert.strictEqual(conn.keyspaceName, parseUri(testClient!.uri).keyspaceName);
- assert.strictEqual(conn.db!.name, parseUri(testClient!.uri).keyspaceName);
+ assert.strictEqual(conn.astraDb!.name, parseUri(testClient!.uri).keyspaceName);
});
it('API ops tests Model.deleteOne()', async () => {
const product1 = new Product({name: 'Product 1', price: 10, isCertified: true, category: 'cat 1'});
@@ -678,8 +678,8 @@ describe('TABLES: Mongoose Model API level tests', async () => {
const { keyspaceName } = parseUri(testClient!.uri);
const childConnection = connection.useDb(keyspaceName, { isTable: false });
- assert.strictEqual(connection.db!.isTable, true);
- assert.strictEqual(childConnection.db!.isTable, false);
+ assert.strictEqual(connection.astraDb!.isTable, true);
+ assert.strictEqual(childConnection.astraDb!.isTable, false);
await connection.close();
});
@@ -695,7 +695,7 @@ describe('TABLES: Mongoose Model API level tests', async () => {
await childConnection.asPromise();
assert.strictEqual(childConnection.client, connection.client);
- assert.notStrictEqual(childConnection.db, connection.db);
+ assert.notStrictEqual(childConnection.astraDb, connection.astraDb);
assert.strictEqual(childConnection.keyspaceName, keyspaceName);
assert.ok((await promise.then(res => res.map(obj => obj.name))).includes(Product.collection.collectionName));
@@ -709,8 +709,8 @@ describe('TABLES: Mongoose Model API level tests', async () => {
await connection.openUri(testClient!.uri, { ...testClient!.options, isTable: true });
await childConnection.asPromise();
- assert.strictEqual(connection.db!.isTable, true);
- assert.strictEqual(childConnection.db!.isTable, false);
+ assert.strictEqual(connection.astraDb!.isTable, true);
+ assert.strictEqual(childConnection.astraDb!.isTable, false);
await connection.close();
});
diff --git a/tests/e2e/tsconfig.json b/tests/e2e/tsconfig.json
index cc3d9ed..9eda111 100644
--- a/tests/e2e/tsconfig.json
+++ b/tests/e2e/tsconfig.json
@@ -1,13 +1,12 @@
{
"compilerOptions": {
"target": "es2020",
- "module": "node16",
- "moduleResolution": "node16",
+ "module": "NodeNext",
+ "moduleResolution": "NodeNext",
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
- "skipLibCheck": true,
"types": ["node"]
},
"include": ["smoke.ts"]
diff --git a/tests/mongooseFixtures.ts b/tests/mongooseFixtures.ts
index cb31242..a172e38 100644
--- a/tests/mongooseFixtures.ts
+++ b/tests/mongooseFixtures.ts
@@ -165,7 +165,7 @@ export async function createMongooseCollections(isTable: boolean) {
}
if (testDebug) {
- mongooseInstance.connection.db!.astraDb.on('commandStarted', ev => {
+ mongooseInstance.connection.astraDb!.astraDb.on('commandStarted', ev => {
console.log(ev.target.url, JSON.stringify(ev.command, null, ' '));
});
}