diff --git a/docs/docs/06_plugins/01_available-plugins/01-transactional/03-pg-promise-adapter.md b/docs/docs/06_plugins/01_available-plugins/01-transactional/03-pg-promise-adapter.md new file mode 100644 index 00000000..4612e0b3 --- /dev/null +++ b/docs/docs/06_plugins/01_available-plugins/01-transactional/03-pg-promise-adapter.md @@ -0,0 +1,98 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# pg-promise adapter + +## Installation + + + + +```bash +npm install @nestjs-cls/transactional-adapter-pg-promise +``` + + + + +```bash +yarn add @nestjs-cls/transactional-adapter-pg-promise +``` + + + + +```bash +pnpm add @nestjs-cls/transactional-adapter-pg-promise +``` + + + + +## Registration + +```ts +ClsModule.forRoot({ + plugins: [ + new ClsPluginTransactional({ + imports: [ + // module in which the database instance is provided + DbModule + ], + adapter: new TransactionalAdapterPgPromise({ + // the injection token of the database instance + dbInstanceToken: DB, + }), + }), + ], +}), +``` + +## Typing & usage + +The `tx` property on the `TransactionHost` is typed as [`Task`](https://vitaly-t.github.io/pg-promise/Task.html). + +## Example + +```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', + 'john@acme.com', + ); + const foundUser = await this.userRepository.getUserById(r1.id); + // highlight-end + assert(foundUser.id === user.id); + } +} +``` + +```ts title="user.repository.ts" +@Injectable() +class UserRepository { + constructor( + private readonly txHost: TransactionHost, + ) {} + + async getUserById(id: number) { + // highlight-start + // txHost.tx is typed as Task + return this.txHost.tx.one(`SELECT * FROM user WHERE id = $1`); + // highlight-end + } + + async createUser(name: string, email: string) { + return this.txHost.tx.none( + `INSERT INTO user (name, email) VALUES ($1, $2)`, + [name, email], + ); + } +} +``` diff --git a/docs/docs/06_plugins/01_available-plugins/01-transactional/index.md b/docs/docs/06_plugins/01_available-plugins/01-transactional/index.md index f0f179de..e7ef36c9 100644 --- a/docs/docs/06_plugins/01_available-plugins/01-transactional/index.md +++ b/docs/docs/06_plugins/01_available-plugins/01-transactional/index.md @@ -42,6 +42,7 @@ Adapters for the following libraries are available: - Prisma (see [@nestjs-cls/transactional-adapter-prisma](./01-prisma-adapter.md)) - Knex (see [@nestjs-cls/transactional-adapter-knex](./02-knex-adapter.md)) +- pg-promise (see [@nestjs-cls/transactional-adapter-pg-promise](./03-pg-promise-adapter.md)) Adapters _will not_ be implemented for the following libraries: @@ -269,29 +270,29 @@ class AccountService { The `ClsPluginTransactional` constructor takes an options object with the following properties: -- **_`imports`_**`: any[]` +- **_`imports`_**`: any[]` An array of NestJS modules that should be imported for the plugin to work. If the dependencies are available in the global context, this is not necessary. -- **_`adapter`_**`: TransactionalAdapter` - An instance of the adapter that should be used for the plugin. +- **_`adapter`_**`: TransactionalAdapter` + An instance of the adapter that should be used for the plugin. ## TransactionHost Interface The `TransactionHost` interface is the main working interface of the plugin. It provides the following API: -- **_`tx`_**`: Transaction` +- **_`tx`_**`: Transaction` Reference to the currently active transaction. Depending on the adapter implementation for the underlying database library, this can be either a transaction client instance, a transaction object or a transaction ID. If no transaction is active, refers to the default non-transactional client instance (or undefined transaction ID). - **_`withTransaction`_**`(callback: Promise): Promise`\ - **_`withTransaction`_**`(options, callback): Promise` - **_`withTransaction`_**`(propagation, callback): Promise` - **_`withTransaction`_**`(propagation, options, callback): Promise` + **_`withTransaction`_**`(options, callback): Promise` + **_`withTransaction`_**`(propagation, callback): Promise` + **_`withTransaction`_**`(propagation, options, callback): Promise` Runs the callback in a transaction. Optionally takes `Propagation` and `TransactionOptions` as the first one or two parameters. -- **_`withoutTransaction`_**`(callback): Promise` +- **_`withoutTransaction`_**`(callback): Promise` Runs the callback without a transaction (even if one is active in the parent scope). -- **_`isTransactionActive`_**`(): boolean` +- **_`isTransactionActive`_**`(): boolean` Returns whether a CLS-managed transaction is active in the current scope. ### Transactional decorator interface