https://github.com/kartava/nestjs-pgkit
Pgkit module for Nest framework (node.js) 🍉
https://github.com/kartava/nestjs-pgkit
javascript nest nestjs nodejs pgkit sql typescript
Last synced: 6 months ago
JSON representation
Pgkit module for Nest framework (node.js) 🍉
- Host: GitHub
- URL: https://github.com/kartava/nestjs-pgkit
- Owner: kartava
- License: mit
- Created: 2024-09-17T00:25:53.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-09-19T15:07:51.000Z (almost 2 years ago)
- Last Synced: 2024-10-16T23:01:02.259Z (over 1 year ago)
- Topics: javascript, nest, nestjs, nodejs, pgkit, sql, typescript
- Language: TypeScript
- Homepage:
- Size: 50.8 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[pgkit](https://www.pgkit.dev/packages/client/) module
for [Nest](https://github.com/nestjs/nest).
## Contents
* [nestjs-pgkit](#nestjs-pgkit)
* [Installation](#installation)
* [Basic import](#basic-import)
* [Multiple databases](#multiple-databases)
* [Async configuration](#async-configuration)
* [License](#license)
###### npm
```bash
npm i --save nestjs-pgkit @pgkit/client
```
###### yarn
```bash
yarn add nestjs-pgkit @pgkit/client
```
Once the installation process is complete, we can import the `PgKitModule` into the root `AppModule`.
> app.module.ts
```typescript
import { Module } from "@nestjs/common";
import { PgKitModule } from "nestjs-pgkit";
@Module({
imports: [
PgKitModule.forRoot({
connectionUri: "postgres://user:password@localhost:5432/test",
}),
],
})
export class AppModule {}
```
The `forRoot()` method supports configuration properties described below.
PgKit options
connectionUri
Connection URI
PgKitModule options
name
Connection client name. Used to inject different db connections (default: default)
toRetry
Function that determines whether the module should attempt to connect upon failure
(err: any) => boolean
err parameter is error that was thrown
verboseRetryLog
If true, will show verbose error messages on each connection retry (default: false)
retryAttempts
Number of attempts to connect to the database (default: 10)
retryDelay
Delay between connection retry attempts (ms) (default: 3000)
Once this is done, the pgkit client will be available to inject across the entire project (without needing to
import any modules), for example:
> app.service.ts
```typescript
import { Injectable } from "@nestjs/common";
import { Client, sql } from "@pgkit/client";
import { InjectClient } from "nestjs-pgkit";
@Injectable()
export class AppService {
constructor(
@InjectClient()
private readonly client: Client,
) {}
getGreeting(): Promise {
return this.client.oneFirst(sql`SELECT 'Hello World!';`);
}
}
```
Some projects require multiple database connections. This can also be achieved with this module.
To work with multiple clients, first create the clients. In this case, client naming becomes **mandatory**.
```typescript
@Module({
imports: [
PgKitModule.forRoot({
connectionUri: "postgres://user:password@users_db_host:5432/users",
}),
PgKitModule.forRoot({
name: "ALBUMS_CLIENT",
connectionUri: "postgres://user:password@albums_db_host:5432/albums",
}),
],
})
export class AppModule {}
```
> **Notice** If you don't set the `name` for a client, its name is set to `default`. Please note that you shouldn't
> have multiple clients without a name, or with the same name, otherwise they will get overridden.
Now you can inject the pgkit client for a given client name:
```typescript
@Injectable()
export class AlbumsService {
constructor(
@InjectClient()
private usersClient: Client,
@InjectClient("ALBUMS_CLIENT")
private albumsClient: Client,
) {}
}
```
You may want to pass your `PgKitModule` options asynchronously instead of statically.
In this case, use the `forRootAsync()` method, which provides several ways to deal with async configuration.
One approach is to use a factory function:
```typescript
PgKitModule.forRootAsync({
useFactory: () => ({
connectionUri: "postgres://user:password@users_db_host:5432/users",
}),
});
```
Our factory behaves like any other [asynchronous provider](https://docs.nestjs.com/fundamentals/async-providers)
(e.g., it can be `async` and it's able to inject dependencies through `inject`).
```typescript
PgKitModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
connectionUri: configService.get("DATABASE_URL"),
}),
inject: [ConfigService],
});
```
Alternatively, you can use the `useClass` syntax:
```typescript
PgKitModule.forRootAsync({
useClass: PgKitConfigService,
});
```
The construction above will instantiate `PgKitConfigService` inside `PgKitModule` and use it to provide
an options object by calling `createPgKitOptions()`. Note that this means that the `PgKitConfigService`
has to implement the `PgKitOptionsFactory` interface, as shown below:
```typescript
@Injectable()
class PgKitConfigService implements PgKitOptionsFactory {
createPgKitOptions(): PgKitModuleOptions {
return {
connectionUri: "postgres://user:password@users_db_host:5432/users",
};
}
}
```
In order to prevent the creation of `PgKitConfigService` inside `PgKitModule` and use a provider imported
from a different module, you can use the `useExisting` syntax.
```typescript
PgKitModule.forRootAsync({
imports: [ConfigModule],
useExisting: ConfigService,
});
```
This construction works the same as `useClass` with one critical difference - `PgKitModule` will lookup
imported modules to reuse an existing `ConfigService` instead of instantiating a new one.
> Make sure that the `name` property is defined at the same level as the `useFactory`, `useClass`, or
> `useValue` property. This will allow Nest to properly register the pool under the appropriate injection token.
```typescript
PgKitModule.forRootAsync({
name: "ALBUMS_CLIENT",
useFactory: () => ({
connectionUri: postgresConnectionUri,
}),
})
```