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

@webundsoehne/nestjs-util

v7.1.9

Published

NestJS skeleton util library

Downloads

2,173

Readme


@webundsoehne/nestjs-util

Version Downloads/week Dependencies semantic-release

Description

This is a collection of useful modules for creating a NestJS project. Mostly all of these modules are used by the in-house boilerplate of Web & Söhne.

Modules

Decorators

Retry Decorator

Wrap a class method with this decorator to retry it couple of more times. Useful for external service dependent tasks.

@Timeout(MigrationTask.name, 0)
@Retry({
  name: MigrationTask.name,
  retry: 24,
  interval: 3 * 1000
})
async migrate(): Promise<void> {
  try {
    await this.connection.runMigrations({ transaction: 'all' })
  } catch (error) {
    this.logger.error(error.message)

    throw error
  }
}

UseMaintenanceLocker Decorator

Whenever the given class method fires, it will also activate the maintenance mode through MaintenanceModule. For this MaintenanceModule should be injected in to the context of the given module.

@Timeout(MigrationTask.name, 0)
@UseMaintenanceLocker(MigrationTask.name)
async migrate(): Promise<void> {
  try {
    await this.connection.runMigrations({ transaction: 'all' })
  } catch (error) {
    this.logger.error(error.message)

    throw error
  }
}

Filters

We implemented a generic ExceptionFilter called GlobalExceptionFilter, which catches all errors and sets the payload to a userfriendly information. The real exception and stacktrace will be just logged in debug logger mode.

Usage

import { GlobalExceptionFilter } from '@webundsoehne/nestjs-util'

@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: GlobalExceptionFilter
    }
  ]
})
class ServerModule implements NestModule {}

Reporting to sentry.io

GlobalSentryExceptionFilter extends the functionality of the GlobalExceptionFilter with additional reporting of errors to sentry.io. The options for sentry need to be set in the config file. At least the dsn has to be defined for a successful initialization. If the initialization was not successful, a warning will be displayed and the filter behaves as the base GlobalExceptionFilter. By default, only unhandled or critical exceptions with HTTP statuscode >= 500 will be reported. Setting the optional config param reportAll to true will report all exceptions to sentry e.g. HttpExceptions, AuthorizationExceptions etc.

This filter requires the @sentry/node package to be installed in your project. Please add it to your package.json dependencies.

Example sentry config

sentry:
  dsn: https://[email protected]/12312345
  environment: appname_production
  reportAll: false

Http

The HttpExceptionFilter extends from the GlobalExceptionFilter and just catches all HttpException errors. It just overwrites the protected payload() method, which builds the message for the user.

Usage

import { HttpExceptionFilter, GlobalExceptionFilter } from '@webundsoehne/nestjs-util'

@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: GlobalExceptionFilter
    },
    {
      provide: APP_FILTER,
      useClass: HttpExceptionFilter
    }
  ]
})
class ServerModule implements NestModule {}

Bad-Request

The BadRequestExceptionFilter extends from the GlobalExceptionFilter and just catches BadRequestException errors. This will handle the complex validation error messages (ValidationError) in the overwritten payload() method, which just happens on BadRequestException errors.

We don't handle them in the normal HttpExceptionFilter because of performance reasons.

Usage

I hope you recognized that the order of the exception filters is relevant and required.

import { BadRequestExceptionFilter, HttpExceptionFilter, GlobalExceptionFilter } from '@webundsoehne/nestjs-util'

@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: GlobalExceptionFilter
    },
    {
      provide: APP_FILTER,
      useClass: HttpExceptionFilter
    },
    {
      provide: APP_FILTER,
      useClass: BadRequestExceptionFilter
    }
  ]
})
class ServerModule implements NestModule {}

Middleware

The middleware of the maintenance module uses directly the MaintenanceService to check if there exists a lock file and raises the correct exception. You will see the implementation in the usage block above.

Info-Header

The information header middleware is a really short NestMiddleware which set the X-Api-Name and X-Api-Version response header out of the process.env data. Both environment variables will be set with the setEnvironmentVariables util function, which loads the information from the package.json.

Usage

import { SetApiInfoHeaderMiddleware, setEnvironmentVariables } from '@webundsoehne/nestjs-util'

class ServerModule implements NestModule {
  async configure(consumer: MiddlewareConsumer): Promise<any> {
    await setEnvironmentVariables()

    consumer.apply(SetApiInfoHeaderMiddleware).forRoutes({ path: '*', method: RequestMethod.ALL })
  }
}

Modules

Maintenance

The maintenance module gives you the possibility to generate and remove a lock file, as well as checking if the lock file exists and throwing a preconfigured ServiceUnavailableException error. You may use the maintenance module anywhere in your project, e.g. for database migrations.

Usage

import { MaintenanceMiddleware, MaintenanceModule } from '@webundsoehne/nestjs-util'

@Module({
  imports: [MaintenanceModule]
})
class ServerModule implements NestModule {
  async configure(consumer: MiddlewareConsumer): Promise<any> {
    consumer.apply(MaintenanceMiddleware).forRoutes({ path: '*', method: RequestMethod.ALL })
  }
}

Methods

| Name | Return | Description | | -------------- | ------- | ------------------------------------- | | enable | void | Create the configured lock file | | disable | void | Remove the generated lock file | | isEnabled | Boolean | Check if there is already a lock file | | throwException | void | Throw the preconfigured exception |

Configuration

If there is no misc.maintenanceNotification set, it will be generated with following template string: `${url.basePath} is currently down for maintenance`

| Key | Type | Default | Description | | ---------------------------- | ------ | ------------------ | ------------------------------------------------------------- | | url.basePath | String | | The base API url of your project | | misc.maintenanceNotification | String | (see hint above) | The notification, which will be thrown in case of maintenance | | misc.lockfile | String | 'maintenance.lock' | The filepath of the projects's maintenance lock file |

Providers

Config

This is a NestJS service which allows you to use the great config library with decorators. For scripts or in common no classes, you can use it normally too.

Important

The @Configurable() has to be the last decorator before the function is initiated.

Usage

import { ConfigParam, ConfigService, Configurable, InjectConfig } from '@webundsoehne/nestjs-util'

// 1. the old (static) way
const configValue1 = ConfigService.get('value')

class CustomService {
  // 2. inject the whole config service, normally you wont use this ways
  constructor ( @InjectConfig() private readonly config: ConfigService) {
    const configValue2 = this.config.get('value')
  }

  // 3. load the config directly as function parameter
  @AnythingElse()
  @Configurable()
  testConfig (@ConfigParam('value', 'default-value') value3?: string) {
    ...
  }
}

Logger

Customized logger service, which uses winston for nicer output.

Usage

Set an instance of the logger to the application during creation as part of the NestApplicationOptions.

import { LoggerService } from '@webundsoehne/nestjs-util'

const app = await NestFactory.create<INestApplication>(ServerModule, new FastifyAdapter(), {
  logger: new LoggerService()
})

After the logger got set to the application, all NestJS logging output will be handled by our customized logger.

import { Logger } from '@nestjs/common'

class CustomService {
  private readonly logger: Logger = new Logger(this.constructor.name)
  private readonly loggerWithoutContext: Logger = new Logger()

  constructor() {
    this.logger.verbose('log message')
    // [2020-01-01T12:00:00.000Z] [verbose] [CustomService] - log message
    this.logger.verbose('log message, with custom context', 'ForcedContext')
    // [2020-01-01T12:00:00.000Z] [verbose] [ForcedContext] - log message, with custom context

    this.logger.loggerWithoutContext('log message')
    // [2020-01-01T12:00:00.000Z] [verbose] [LoggerService] - log message
    this.logger.loggerWithoutContext('log message, with custom context', 'ForcedContext')
    // [2020-01-01T12:00:00.000Z] [verbose] [ForcedContext] - log message, with custom context
  }
}

Pipes

Extended pipes provide capabilities over the default ones for better interacting with this library.

Validation Pipe

This validation pipe extends the default pipe for class-validator while it also provides a way to override the settings for a given path utilizing the accompanying decorator.

Usage

This can either be used with a useClass or to extend the options useFactory. The default ValidationPipeOptions are { whitelist: true }.

import { Module } from '@nestjs/common'
import { APP_PIPE } from '@nestjs/core'
import { ExtendedValidationPipe } from '@webundsoehne/nestjs-util'

@Module({
  providers: [
    {
      provide: APP_PIPE,
      useClass: ExtendedValidationPipe
    }
  ]
})
export class ServerModule {}

Stay in touch