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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@marinade.finance/nestjs-common

v4.3.1

Published

Shared NestJS building blocks (database, telemetry, auth, rate limiting)

Readme

@marinade.finance/nestjs-common

Shared NestJS building blocks for Marinade Finance services. Provides database (PostgreSQL via slonik), Redis, authentication, rate limiting, telemetry/APM, Prometheus metrics, structured logging, Swagger setup, and graceful shutdown — all configured through environment variables.

Install

pnpm add @marinade.finance/nestjs-common

Peer dependencies: @nestjs/common, @nestjs/core, @nestjs/swagger, @willsoto/nestjs-prometheus, nestjs-pino, prom-client. Optional: elastic-apm-node.

Modules

Database

PostgreSQL connection pool via slonik with automatic migrations.

Database helpers live under the ./database subpath so services that don't use a database don't need to install slonik. slonik is an optional peer dependency — install it in consumers that import this module.

import {
  DatabaseModule,
  DatabaseService,
} from '@marinade.finance/nestjs-common/database'

DatabaseModule.forRoot(() => ({
  url: getDatabaseUrl(),
  maxPoolSize: getDatabasePoolSize(),
}))

| Variable | Required | Description | |---|---|---| | DATABASE_URL | Yes | PostgreSQL connection string | | DATABASE_POOL_SIZE | No | Max pool connections |

Redis

import { RedisModule } from '@marinade.finance/nestjs-common'

RedisModule.forRoot(() => ({
  url: getRedisUrl(),
  password: getRedisPassword(),
}))

| Variable | Required | Description | |---|---|---| | REDIS_URL | Yes | Redis connection URL | | REDIS_PASSWORD | No | Redis password |

Auth

JWT-based authentication guard with glob-pattern user whitelisting.

| Variable | Required | Description | |---|---|---| | JWT_SECRET | Yes | JWT signing secret | | API_SECRET | Yes | API secret key | | ALLOWED_USERS | Conditional | Comma-separated usernames/glob patterns |

Rate Limiting

Per-route rate limiting via @RateLimit() decorator and RateLimitGuard.

Telemetry / APM

Elastic APM integration. Call startApm() before NestFactory.create().

APM helpers live under the ./apm subpath so services that don't use APM don't need to install elastic-apm-node. elastic-apm-node is an optional peer dependency — install it in consumers that import this module.

import { startApm } from '@marinade.finance/nestjs-common/apm'

const agent = startApm() // reads env vars, returns undefined if disabled

| Variable | Required | Default | Description | |---|---|---|---| | ELASTIC_APM_ENABLED / OTEL_ENABLED / otel.enabled | No | false | Enable telemetry (first match wins) | | ELASTIC_APM_SERVER_URL / otel.url | When enabled | - | APM server endpoint | | ELASTIC_APM_SECRET_TOKEN / otel.secretToken | No | - | APM auth token |

Metrics

Prometheus metrics server with health/readiness endpoints.

import { startMetricsServer } from '@marinade.finance/nestjs-common'

const server = startMetricsServer({
  port: getMetricsPort(),
  healthz: true,
  readinessCheck: () => ({ ready: true }),
})

| Variable | Required | Default | Description | |---|---|---|---| | METRICS_PORT | No | 9000 | Prometheus metrics port |

Logging

Structured JSON logging via pino with ECS format for Elastic.

import { getPinoElasticConfigBuilder, customLogLevel } from '@marinade.finance/nestjs-common'

Bootstrap Utilities

import { setupSwagger, setupGracefulShutdown } from '@marinade.finance/nestjs-common'

setupSwagger(app, { title: 'My API' })
setupGracefulShutdown(app, { metricsServer, beforeShutdown: () => { /* mark not ready */ } })

Service Configuration

| Variable | Required | Default | Description | |---|---|---|---| | SERVICE_NAME / ELASTIC_APM_SERVICE_NAME / serviceName | Yes | - | Service name (first match wins) | | PORT | No | 3000 | HTTP server port |

Config Helpers

All env helpers from @marinade.finance/config-common are re-exported:

import { getEnvVar, getBoolEnvVar, getJsonEnvVar } from '@marinade.finance/nestjs-common'

Single key or fallback arrays are supported:

getEnvVar(['PRIMARY_KEY', 'FALLBACK_KEY'], 'default')

Example

main.ts — bootstrap

import { NestFactory } from '@nestjs/core'
import {
  startMetricsServer,
  setupSwagger,
  setupGracefulShutdown,
  getPinoElasticConfigBuilder,
  customLogLevel,
  getServiceName,
  getPort,
  getMetricsPort,
  getServiceEnvironment,
} from '@marinade.finance/nestjs-common'
import { startApm } from '@marinade.finance/nestjs-common/apm'
import { LoggerModule } from 'nestjs-pino'
import { AppModule } from './app.module'

// APM — must be called before NestFactory.create()
startApm()

async function bootstrap() {
  const serviceName = getServiceName()

  const app = await NestFactory.create(
    AppModule.register(serviceName),
    { bufferLogs: true },
  )

  // Swagger docs at /docs
  setupSwagger(app, { title: serviceName })

  // Metrics + health/readiness on separate port
  const metricsServer = startMetricsServer({
    port: getMetricsPort(),
    healthz: true,
    readinessCheck: () => ({ ready: true }),
  })

  // Graceful shutdown: signals → mark not-ready → close app → close metrics
  setupGracefulShutdown(app, { metricsServer })

  await app.listen(getPort())
}
void bootstrap()

app.module.ts — wiring modules

import { DynamicModule, Module } from '@nestjs/common'
import { LoggerModule } from 'nestjs-pino'
import {
  // Database env helpers
  getDatabaseUrl,
  getDatabasePoolSize,
  // Redis
  RedisModule,
  getRedisUrl,
  getRedisPassword,
  // Metrics
  MetricsModule,
  // Logging
  getPinoElasticConfigBuilder,
  customLogLevel,
  getServiceEnvironment,
} from '@marinade.finance/nestjs-common'
import { DatabaseModule } from '@marinade.finance/nestjs-common/database'

@Module({})
export class AppModule {
  static register(serviceName: string): DynamicModule {
    return {
      module: AppModule,
      imports: [
        // Structured logging (pino → ECS JSON)
        LoggerModule.forRoot(
          getPinoElasticConfigBuilder()({
            serviceName,
            serviceVersion: '1.0.0',
            serviceEnvironment: getServiceEnvironment(),
            logLevel: 'info',
            customLogLevel,
          }),
        ),

        // PostgreSQL pool + auto-migrations from ./migrations
        DatabaseModule.forRoot(() => ({
          url: getDatabaseUrl(),
          maxPoolSize: getDatabasePoolSize(),
        })),

        // Redis (global)
        RedisModule.forRoot(() => ({
          url: getRedisUrl(),
          password: getRedisPassword(),
        })),

        // Prometheus HTTP counter
        MetricsModule.forRoot(() => ({ port: 9000 })),
      ],
    }
  }
}