From b4f5c29b9a5cad3afa37503940f5c3c2f0f82ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20=C5=A0vanda?= <46406259+Papooch@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:33:17 +0200 Subject: [PATCH] docs(transactional-adapter-mongoose): add docs --- .../01-transactional/07-mongoose-adapter.md | 119 ++++++++++++++++++ .../src/lib/transactional-adapter-mongoose.ts | 2 + 2 files changed, 121 insertions(+) create mode 100644 docs/docs/06_plugins/01_available-plugins/01-transactional/07-mongoose-adapter.md diff --git a/docs/docs/06_plugins/01_available-plugins/01-transactional/07-mongoose-adapter.md b/docs/docs/06_plugins/01_available-plugins/01-transactional/07-mongoose-adapter.md new file mode 100644 index 0000000..e7c0ba6 --- /dev/null +++ b/docs/docs/06_plugins/01_available-plugins/01-transactional/07-mongoose-adapter.md @@ -0,0 +1,119 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Mongoose adapter + +## Installation + + + + +```bash +npm install @nestjs-cls/transactional-adapter-mongoose +``` + + + + +```bash +yarn add @nestjs-cls/transactional-adapter-mongoose +``` + + + + +```bash +pnpm add @nestjs-cls/transactional-adapter-mongoose +``` + + + + +## Registration + +```ts +ClsModule.forRoot({ + plugins: [ + new ClsPluginTransactional({ + imports: [ + // module in which the Connection instance is provided + MongooseModule, + ], + adapter: new TransactionalAdapterMongoose({ + // the injection token of the mongoose Connection + mongooseConnectionToken: Connection, + }), + }), + ], +}); +``` + +## Typing & usage + +To work correctly, the adapter needs to inject an instance of mongoose [`Connection`](). + +Due to how transactions work in MongoDB, [and in turn in Mongoose](https://mongoosejs.com/docs/transactions.html), the usage of the Mongoose adapter is a bit different from the others. + +The `tx` property on the `TransactionHost` does _not_ refer to any _transactional_ instance, but rather to a [`ClientSession`](https://mongodb.github.io/node-mongodb-native/6.7/classes/ClientSession.html) instance of `mongodb`, with an active transaction, or `null` when no transaction is active. + +Queries are not executed using the `ClientSession` instance, but instead the `ClientSession` instance or `null` is passed to the query as the `session` option. + +:::important + +The `TransactionalAdapterMongoose` _does not support_ the ["Transaction Proxy"](./index.md#using-the-injecttransaction-decorator) feature, because proxying a `null` value is not supported by the JavaScript Proxy. + +:::: + +## Example + +```ts title="database.schemas.ts" +const userSchema = new Schema({ + name: String, + email: String, +}); + +const User = mongoose.model('user', userSchema); +``` + +```ts title="user.service.ts" +@Injectable() +class UserService { + constructor(private readonly userRepository: UserRepository) {} + + @Transactional() + async runTransaction() { + // highlight-start + // both methods are executed in the same transaction + const user = await this.userRepository.createUser('John'); + const foundUser = await this.userRepository.getUserById(user._id); + // highlight-end + assert(foundUser._id === user._id); + } +} +``` + +```ts title="user.repository.ts" +@Injectable() +class UserRepository { + constructor( + private readonly txHost: TransactionHost, + ) {} + + async getUserById(id: ObjectId) { + // txHost.tx is typed as ClientSession + return await User.findById(id) + // highlight-start + .session(this.txHost.tx); + // highlight-end + } + + async createUser(name: string) { + const user = new User({ name: name, email: `${name}@email.com` }); + await user + // highlight-start + .save({ session: this.txHost.tx }); + // highlight-end + return user; + } +} +``` diff --git a/packages/transactional-adapters/transactional-adapter-mongoose/src/lib/transactional-adapter-mongoose.ts b/packages/transactional-adapters/transactional-adapter-mongoose/src/lib/transactional-adapter-mongoose.ts index fb13503..04da878 100644 --- a/packages/transactional-adapters/transactional-adapter-mongoose/src/lib/transactional-adapter-mongoose.ts +++ b/packages/transactional-adapters/transactional-adapter-mongoose/src/lib/transactional-adapter-mongoose.ts @@ -49,6 +49,8 @@ export class TransactionalAdapterMongoose } } + supportsTransactionProxy = false; + optionsFactory(connection: Connection) { return { wrapWithTransaction: async (