NestJS Integration
@sqb/nestjs wires a SqbClient into a NestJS
application as an injectable provider, with the connection lifecycle (connect on bootstrap,
close on shutdown) managed for you.
npm install @sqb/nestjs @sqb/connect @sqb/builder
@sqb/nestjs doesn't ship a database driver itself — install and import a
database adapter (e.g. @sqb/postgres) the same way you
would with a plain @sqb/connect client.
Registering the module
SqbModule.forRoot()
Pass connection options directly via useValue:
import '@sqb/postgres';
import { Module } from '@nestjs/common';
import { SqbModule } from '@sqb/nestjs';
@Module({
imports: [
SqbModule.forRoot({
useValue: {
dialect: 'postgres',
host: 'localhost',
database: 'mydb',
user: 'myuser',
password: 'mypassword',
},
}),
],
})
export class AppModule {}
Under the hood this delegates to SqbCoreModule, which provides an SqbClient instance built
from the given SqbClientConnectionOptions and exposes it for injection (see
Injecting the client below).
SqbModule.forRootAsync()
Use forRootAsync() when the connection options need to be built asynchronously — for example,
read from a NestJS ConfigService:
import '@sqb/postgres';
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { SqbModule } from '@sqb/nestjs';
@Module({
imports: [
SqbModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
dialect: 'postgres',
host: config.get('DB_HOST'),
database: config.get('DB_NAME'),
user: config.get('DB_USER'),
password: config.get('DB_PASSWORD'),
}),
}),
],
})
export class AppModule {}
useFactory may return its result synchronously or as a Promise — either form is accepted.
Injecting the client
By default, the provider token is the SqbClient class itself, so a consumer can inject it by
type without an explicit @Inject():
import { Injectable } from '@nestjs/common';
import { SqbClient } from '@sqb/connect';
@Injectable()
export class UsersService {
constructor(private readonly client: SqbClient) {}
findAll() {
return this.client.execute('select * from users');
}
}
Multiple connections
To register more than one connection in the same application (or to avoid depending on the
SqbClient class as a token), pass a custom token and inject it explicitly with @Inject():
SqbModule.forRoot({
token: 'READ_REPLICA',
useValue: { dialect: 'postgres', host: 'replica.internal', database: 'mydb' },
});
import { Inject, Injectable } from '@nestjs/common';
import { SqbClient } from '@sqb/connect';
@Injectable()
export class ReportsService {
constructor(
@Inject('READ_REPLICA')
private readonly client: SqbClient,
) {}
}
Module options
global
Set global: true to register the module as a global NestJS module, so the SqbClient
provider is available application-wide without re-importing SqbModule (or the module that
imports it) into every feature module:
SqbModule.forRoot({
global: true,
useValue: { dialect: 'postgres', database: 'mydb' },
});
lazyConnect
By default the module calls client.test() during
onApplicationBootstrap to verify connectivity and log the result. Set lazyConnect: true to
skip this and connect lazily on first use instead:
SqbModule.forRoot({
useValue: {
dialect: 'postgres',
database: 'mydb',
lazyConnect: true,
},
});
shutdownWaitMs
Number of milliseconds to wait for in-flight operations when closing the connection pool during
onApplicationShutdown (passed straight through to
client.close()). Defaults to 10:
SqbModule.forRoot({
useValue: {
dialect: 'postgres',
database: 'mydb',
shutdownWaitMs: 5000,
},
});
logger
Pass a NestJS LoggerService instance (or a string logger context name) to control where
connection lifecycle messages (Waiting to connect to Database..., Database connection established, connection failures) are logged.
envPrefix
Any connection field left unset in useValue/useFactory is filled in from environment
variables, using envPrefix (default 'SQB_') as the variable prefix:
| Field | Environment variable |
|---|---|
dialect | ${envPrefix}DIALECT |
name | ${envPrefix}CONNECTION_NAME |
host | ${envPrefix}HOST |
port | ${envPrefix}PORT |
database | ${envPrefix}DATABASE |
schema | ${envPrefix}SCHEMA |
user | ${envPrefix}USER |
password | ${envPrefix}PASSWORD |
driver | ${envPrefix}DRIVER |
pool.max | ${envPrefix}POOL_MAX |
pool.min | ${envPrefix}POOL_MIN |
pool.idleTimeoutMillis | ${envPrefix}POOL_IDLE_TIMEOUT |
pool.acquireTimeoutMillis | ${envPrefix}POOL_ACQUIRE_TIMEOUT |
pool.acquireMaxRetries | ${envPrefix}POOL_ACQUIRE_MAX_RETRIES |
pool.acquireRetryWait | ${envPrefix}POOL_ACQUIRE_RETRY_WAIT |
pool.fifo | ${envPrefix}POOL_FIFO |
pool.maxQueue | ${envPrefix}POOL_MAX_QUEUE |
pool.minIdle | ${envPrefix}POOL_MIN_IDLE |
pool.validation | ${envPrefix}POOL_VALIDATION |
pool.houseKeepInterval | ${envPrefix}POOL_HOUSE_KEEP_INTERVAL |
Values already present in useValue/the object returned by useFactory always win — the
environment is only consulted for fields left unset. This lets you keep secrets like the
password out of source and supply everything through the environment instead:
// .env
// SQB_DIALECT=postgres
// SQB_HOST=localhost
// SQB_DATABASE=mydb
// SQB_USER=myuser
// SQB_PASSWORD=mypassword
SqbModule.forRoot(); // options come entirely from SQB_* environment variables
Pass a custom prefix if SQB_ collides with something else in your environment:
SqbModule.forRoot({ envPrefix: 'MYAPP_DB_' });
See also
SqbModuleAPI referenceSqbModuleOptions,SqbModuleAsyncOptions, andSqbClientConnectionOptions- Creating a Client for the underlying
@sqb/connectconfiguration