npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@betsys-nestjs/postgres

v6.2.0

Published

This library is responsible for handling PosgreSQL connections and queries.

Downloads

76

Readme

Postgres library

This package is an implementation of node-postgres library compatible with NestJS modules. It contains connection pooling, cursor queries logic, customizable logging and monitoring.

Dependencies

| Package | Version | | ---------------- | ------- | | @types/pg | ^8.0.0 | | pg | ^8.0.0 | | pg-cursor | ^2.0.0 | | @nestjs/common | ^10.0.0 | | @nestjs/terminus | ^10.0.0 | | reflect-metadata | ^0.1.13 | | @nestjs/core | ^10.0.0 | | rxjs | ^7.8.0 |

Usage

To create a new PG pool of connection simply add this to your module imports and provide config as the first parameter:

import { Module } from '@nestjs/common';
import { PostgresqlModule } from '@betsys-nestjs/postgres'

@Module({
    imports: [
        PostgresqlModule.forFeature({
            uri: 'postgresql://postgres:pass@host:port/database',
            poolSize: 10,
            batchSize: 10,
        }),
    ],
})
class InfrastructureModule {}

And to use the connection just import PostgresConnection provider using the InjectConnectionProvider decorator:

class MyPostgreSQLOperation {
    constructor(
        @InjectConnectionProvider()
        private readonly postgresConnectionService: PostgresConnection,
    ) {}

    async execute(): Promise<Result> {
        const result = this.postgresConnectionService.executeWithPoolConnection((connection) => {
            return connection.query<Result>('SELECT * FROM get_my_data()');
        });

        if (result.rows.length === 0) {
            throw new NotFoundException(`Data not found.`);
        }

        return result.rows[0];
    }
}

To use cursor to load data in bulks (to lower the memory usage when working with big query results), you can import PostgresCursorUtils that returns AsyncGenerator:

@Injectable()
export class LoadDataCursorOperation {
    constructor(
        @InjectCursorUtils()
        private readonly postgresCursorUtils: PostgresCursorUtils,
    ) {
    }

    public getCursor(ticketIds: number[]): AsyncGenerator<ResultRow[]> {
        return this.postgresCursorUtils.queryCursor<ResultRow>(
            'SELECT * FROM get_big_data()',
            'LoadDataCursorOperation', // this is a key for monitoring purposes
            [], // and here you can pass query params  
        );
    }
}

Multiple connection support

To utilize multiple DB connections in the same module you need to name them by defining dbHandle value:

@Module({
    imports: [
        PostgresqlModule.forFeature({
            uri: 'postgresql://betsys@postgres/live',
            poolSize: 10,
            batchSize: 10,
            dbHandle: 'DB1'
        }),
        PostgresqlModule.forFeature({
            uri: 'postgresql://betsys@postgres/live',
            poolSize: 10,
            batchSize: 10,
            dbHandle: 'DB2'
        }),
    ],
})
class InfrastructureModule {}

And to inject particular connection just add the name to the annotation:

class MyPostgreSQLOperation {
    constructor(
        @InjectConnectionProvider('DB1')
        private readonly postgresConnectionService: PostgresConnection,
        @InjectCursorUtils('DB1')
        private readonly postgresCursorUtils: PostgresCursorUtils,
    ) {}
}

Monitoring and Logger support

The library is ready to work with monitoring and logger. To enable it you need to implement your own monitoring and logger service based on abstraction provided by this library.

Monitoring

There are two different monitoring parts that can be independently set in the config:

  • Time monitoring - used for monitoring of query time, your provided service must implement PostgresTimeMonitoringInterface. Implementation of startTimerExecutionTime starts your custom timer returning a function which stops the timer.

  • Connection monitoring - used for observing count of connections to database via this library. To use this monitoring type, you must implement PostgresConnectionMonitoringInterface.

Example of connection monitoring using @betsys-nestjs/monitoring:

import {
    AbstractMonitoringService,
    Gauge,
    InjectMonitoringConfig,
    InjectMonitoringRegistry, 
    MonitoringConfig,
    Registry,
} from '@betsys-nestjs/monitoring';
import { ConnectionMonitoringService } from '@betsys-nestjs/postgres';
import { Injectable } from '@nestjs/common';

@Injectable()
export class PostgresConnectionMonitoring extends AbstractMonitoringService implements PostgresConnectionMonitoringInterface {
    private readonly SYSTEM_LABEL = 'postgres';

    private readonly connectionGauge: Gauge<string>;

    constructor(
        @InjectMonitoringRegistry() protected readonly registry: Registry,
        @InjectMonitoringConfig() private readonly config: MonitoringConfig,
    ) {
        super(registry);
        this.connectionGauge = this.createMetric(Gauge, {
            name: this.config.getMetricsName('open_connection'),
            help: 'count of currently open connections to postgres DB',
            labelNames: ['system', 'handle'],
            registers: [registry],
        });
    }

    connectionOpened(handle: string): void {
        this.connectionGauge.inc({ system: this.SYSTEM_LABEL, handle }, 1);
    }

    connectionClosed(handle: string): void {
        this.connectionGauge.dec({ system: this.SYSTEM_LABEL, handle }, 1);
    }
}

connectionOpened is called when client is connected to pool and connectionClosed is called when connection is closed.

Logger

Similar to monitoring you can simply implement custom service following PostgresLoggerInterface.

Example using @betsys-nestjs/logger:

import { Injectable } from '@nestjs/common';
import { Logger as NestLogger } from '@betsys-nestjs/logger';
import { Logger } from '@betsys-nestjs/postgres';

@Injectable()
export class PostgresLogger implements PostgresLoggerInterface {
    constructor(private readonly logger: NestLogger) {}

    debug(message: string): void {
        // eslint-disable-next-line no-console
        this.logger.debug(message);
    }

    setContext(context: string): void {
        this.logger.setContext(context);
    }
}

In setContext you can define some context for further logging. debug method is responsible for logging itself so you can either use some console.log or any logger based on your preference like winston etc.

To start using Logger or Monitoring service, you simply insert class references to forFeature method of PostgresModule like this:

PostgresqlModule.forFeature({
    // other config values, 
    logger: PostgresTestLogger,
    monitoring: {
        connection: TestConnectionMonitoringService,
        time: TestTimeMonitoringService,
    },
})