Skip to main content

Base features

The base features of the TypeScript NestJS stack are available for any project based on the stack by default and are not related to special extensions. The features will be enabled by using the provided Nest Application setup functions and K5SDKModule within your application, which also offer configuration options to customize the behavior according to your needs.

NestJS Application setup

The k5 SDK offers functions to easily create and setup a NestApplication with a default configuration. It is recommended to use these functions wihtin your applications for the initial setup, to make sure that your NestApplication is prepared for further features of the K5SDK.

Get default NestApplicationOptions, which applies the K5LoggerService as default logger and default https options:

import { getNestApplicationOptions } from 'k5-sdk';

// get default nest application options
const options = await getNestApplicationOptions();

Create a new NestApplication using the NestApplicationOptions:

import { createNestApplication } from 'k5-sdk';

// create nest app
const app = await createNestApplication(AppModule, options);

Setup the NestApplication with extra configuration (e.g. applying default middlewares, enabling CORS protection, enabling tracing):

import { setupNestApplication } from 'k5-sdk';

// setup nest app and apply middlewares
await setupNestApplication(app, {
dotenvConfig: { path: '.env' }
});

K5SDKModule

The K5SDKModule is a module that is meant to be imported into the root module of your project. It bundles different modules provided in the k5 sdk and enable their features. To ensure flexibility, you have various configuration possibilities like flags for disabling certain modules or setting specific configurations for it. The K5SDKModuleis defined as a global module and therefore all it's providers can be easily used within custom code.

💡tip

Even though the individual modules could be also imported without the K5SDKModule, it is recommended to rather use K5SDKModule as new features shipped will be automatically applied through it.

Use the K5SDKModule within your root module:

import { ConfigModule } from '@nestjs/config';
import { Module } from '@nestjs/common';
import { K5SDKModule } from 'k5-sdk';

@Module({
imports: [
ConfigModule.forRoot(),
// import K5SDKModule with default settings
K5SDKModule.forRoot({}),
],
controllers: [],
providers: [],
})
export class AppModule {}

Logging

The K5LoggerService is a logging service provided by the K5SDKModule, which is part of the K5 SDK. It is built on top of winston and provides structured logging with automatic log level configuration from the LOG_LEVEL environment variable.

Usage

By default, the K5LoggerService is used as the default logger in the generated NestJS application. Additionally, K5LoggerService is globally provided by the K5SDKModule, making it available for injection into controllers and services:

@Injectable()
export class SomeService {
constructor(private readonly logger: K5LoggerService) {}

someMethod() {
this.logger.info('Executing someMethod');
}
}

Environment Configuration

For deployed services, the pipeline automatically sets the LOG_LEVEL environment variable.
For local development, LOG_LEVEL should be set in the local .env file. If not set, it defaults to 'INFO'.

Logging Methods

The following logging methods are available:

MethodAliasDescription
errorLogs an error message with stack trace (if provided)
warnLogs a warning message
infologLogs an informational message
debugLogs a debug message
verboseLogs a verbose message

Logging Method Arguments

info, warn, debug, verbose

this.logger.info('message', ...args);
  1. message - The log message
  2. args - Optional arguments (if the first argument is a string, it is used as the log statement context)

Example:

this.logger.info('Pet added successfully', 'Pet Ctx', { foo: 'bar' });

[2025-02-11 16:23:47] [INFO] [Pet Ctx] [traceId: 892dee5801bdb06e] [spanId: 892dee5801bdb06e]: Pet added successfully params: {"foo":"bar"}

error

this.logger.error('message', error.stack, ...args);
  1. message - The log message
  2. stack - Stack trace of the error
  3. args - Optional arguments (if the first argument is a string, it is used as the log statement context)

Log Output Format

Each log statement includes the following information:

  • Timestamp
  • Log Level
  • Context (defaults to caller file name and line number)
  • Trace ID & Span ID (from tracing middleware)
  • Message
  • Additional arguments

Example:

this.logger.log(`Starting "addPet" operation`);

[2025-02-10 16:32:30] [INFO] [src/api/pet/pet.controller.ts:32:17] [traceId: bcee7a9a2b60257e] [spanId: bcee7a9a2b60257e]: Starting "addPet" operation

For more details on tracing integration and traceId/spanId, see Tracing Documentation.

❗️info

Production Logging Format: In production environments, log messages are structured as JSON objects

Custom Log Format

The K5LoggerService can be customised to use a custom log format with Winston:

import * as winston from 'winston';
providers: [
{
provide: K5LoggerService,
useFactory: () =>
new K5LoggerService({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.printf(({ timestamp, level, message }) => {
return `[${timestamp}] [${level.toUpperCase()}]: ${message}`;
})
),
}),
},
],

Customizing K5LoggerService

When importing the K5SDKModule, the global K5LoggerService instance options can be configured by setting k5LoggerServiceOptions:

imports: [
ConfigModule.forRoot(),
K5SDKModule.forRoot({
k5LoggerServiceOptions: {
level: 'debug',
},
}),
],
❗️info

If K5LoggerService is explicitely provided from a NestJS module, the log level is determined by the LOG_LEVEL environment variable.

However, it can also be customized using standard Winston logger options:

providers: [
{
provide: K5LoggerService,
useFactory: () => new K5LoggerService({ level: 'error' }), // Generic winston LoggerOptions
},
],

Setting Context for a Module

The setContext function allows setting a context for logs emitted by a K5LoggerService instance within a specific module:

providers: [
{
provide: K5LoggerService,
useFactory: () => new K5LoggerService().setContext('Pet Context'),
},
],

[2025-02-10 16:39:00] [INFO] [Pet Context] [traceId: 5af8d2390a3a44f3] [spanId: 5af8d2390a3a44f3]: Starting "addPet" operation

Tracing

The TypeScript NestJS stack by default enables tracing for all incoming requests. The tracing information will automatically be applied to all log statements of the service. To access the tracing context, the k5 sdk provides the function getTracingContext().

import { getTracingContext  } from 'k5-sdk';

// get tracing context to access traceId, spanId, parentId
const ctx = getTracingContext();

const traceId = ctx.traceId;
const spanId = ctx.spanId;
const parentId = ctx.parentId;

HTTP requests

To trigger HTTP requests to external services, the k5 sdk offers useful classes and functions.

The K5HttpService offers common methods to trigger HTTP requests based on axios and automatically applies the tracing context to the request. It is provided through the global K5SDKModule and therefore the default instance of K5HttpService can be easily used across the application.

Example usage:


import { K5HttpService } from 'k5-sdk';

export class MyController {
constructor(private httpService: K5HttpService) {
super();
}

async myMethod() {
// trigger a GET request
await this.httpService.get('/my/get/operation');
}

Besides that, common NestJS Dependency Injection can be used to inject the K5HttpService wherever it is required. This way, it is also possible to apply a specific configuration for the used axios instance (see below example) whenever this is needed for a use case.

Example to include the K5HttpService into your module as provider with specific configuration:

import { K5HttpService } from 'k5-sdk';
import { MyController } from './my.controller';

@Module({
imports: [],
controllers: [MyController],
providers: [
{
provide: K5HttpService,
useFactory: () =>
new K5HttpService({
// add specific axios configuration
baseURL: 'https://some.base.url.com'
}),
},
],
})
export class MyModule {}
❗️info

Besides the K5HttpService, it is possible to directly make use of the tracedAxios instance, exported by the k5 sdk.

JWT based authentication

In services built with the TypeScript NestJS stack, any incoming HTTP request is secured by default. The authentication policy is automatically applied by the K5AuthModule, which is included in the K5SDKModule. It expects a valid JWT as bearer token within the Authentication header of the request. If the provided JWT is invalid or it is even completely missing, the request will be rejected automatically and a meaningful error will be returned to the consumer.

Required environment variable

To be able to validate the JWT, the service requires the URI to the issuer of the OIDC provider. It is expected that it is provided within the environment variable OIDC_ISSUER_URI. For the deployed service, the pipeline is taking care for setting the variable, but for local development, please make sure that it is provided in your local .env.

Disable JWT based authentication

If you want to disable the authentication check for your use case, you have two options:

  • Disable JWT check for special routes
  • Disable JWT for the whole application

Disabling the JWT check for dedicated endpoints within your application could be useful in some situations. To do that, you can make use of the @Public decorator offered by the k5-sdk within a controller:

import { Controller, Get } from '@nestjs/common';
import { Public } from 'k5-sdk';

@Controller('/api')
export class AppController {

@Get('/public-route')
@Public()
getPublic(): string {
// no authentication was required to get here
// ...
}
}

Disabling the JWT checks for the whole application can be done by disabling the overall K5AuthModule within the configuration of the K5SDKModule in the root module of your application:

import { Module } from '@nestjs/common';
import { K5SDKModule } from 'k5-sdk';

@Module({
imports: [
K5SDKModule.forRoot({
// disable authentication
disableK5AuthModule: true,
}),
],
})
export class AppModule {}

Health checks

The K5SDKModule automatically comes with built-in endpoints for health checks, liveness and readiness probes which guarantees, that the service is compliant with the common software design standards.

The K5HealthModule by default enables 3 public routes which are not secured by the default authentication checks so that they can be used e.g. for health checks. The health checks, liveness and readiness probes are automatically set up by the pipeline and don't require any specific settings to work.

By default, the following endpoints are provided:

  • GET /health
  • GET /liveness
  • GET /readiness

Configuration

To configure the health module, you can make use of the available configuration options in the K5SDKModule:

import { Module } from '@nestjs/common';
import { K5SDKModule } from 'k5-sdk';

@Module({
imports: [
K5SDKModule.forRoot({
k5HealthModuleOptions: {
// The timeout to wait in ms before the application shuts down
gracefulShutdownTimeoutMs: 3000
}
}),
],
})
export class AppModule {}

To completely customize the endpoints and their behavior, it is recommended to disable the K5HealthModule completely and re-implement the health feature in your application. In this case, please make sure that the helm chart is in sync with the customizations made.

Disable default routes

To disable the default routes, you can use the configuration option in the K5SDKModule:

import { Module } from '@nestjs/common';
import { K5SDKModule } from 'k5-sdk';

@Module({
imports: [
K5SDKModule.forRoot({
// disable health, readiness and liveness routes
disableK5HealthModule: true
}),
],
})
export class AppModule {}

Rate Limit Module

The K5SDKModule automatically comes with built-in support for rate limit to protect your service by controlling the number of requests a client can make within a specified time window.

The K5RateLimitModule is disabled by default. When enabled, it comes with predefined default values.

  • TTL (Time to Live): 60000 milliseconds
  • Limit: 100

Configuration

To configure the rate limit module, you can make use of the available configuration options in the K5SDKModule:

import { Module } from '@nestjs/common';
import { K5SDKModule } from 'k5-sdk';

@Module({
imports: [
K5SDKModule.forRoot({
enableK5RateLimitModule: true,
k5RateLimitModuleOptions: [
{
limit: 20,
ttl: 120000,
},
],
}),
],
})
export class AppModule {}

CORS protection

The TypeScript NestJS stack offers an easy way to enable Cross-Origin Resource Sharing protection within the service project.

The CORS protection is configured through the setupNestApplication() function provided in the k5 SDK and mainly relies on the provided environment variables.

Environment variables

The following environment variables can be used to configure the CORS protection:

  • CORS_POLICY_ENABLED: A boolean value (true or false) to enable or disable CORS.
  • CORS_ORIGIN: A comma-separated list of allowed origins. Each origin must be a valid URL or *.
  • CORS_METHODS: A comma-separated list of allowed HTTP methods (e.g., GET, POST).
  • CORS_HEADERS: A comma-separated list of allowed headers (e.g., Content-Type, Authorization).

Configure CORS in local development

To enable and configure CORS for local development, please ensure that the above described environment variables are set according to your needs in the local .env file.

Configure CORS for a deployed service

Enable CORS protection from hub

  1. Go to Hub and from "k5-projects" tab select the environment that has the service deployment.
  2. Click "Service deployment" tab and search for the service deployment
  3. Choose "Deployment configuration" tab.
  4. Expand "Features" section.
  5. Toggle the "Enable CORS" button to enable it.
  6. Click on "Save" button.
  7. Redeploy the service by rerunning the pipeline from the designer.

Enable CORS protection from configuration management service

Use the Configuration Management API to send the following CORS configuration in request body (in yaml format):

feature:
corsPolicy: true // enable/disable the CORS policy
corsConfiguration:
corsOrigin: '*' // for allowed CORS origin
corsMethods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS' // the allowed CORS methods
corsHeaders: '' // CORS headers that are allowed

This will override the CORS default configured values.

Helmet

The TypeScript NestJS stack offers an easy way to enable helmet protection within the service project.

The helmet protection can be enabled through the Nest Application Setup. To switch it on, use the configuration option enableHelmetProtection. To configure helmet according to your needs, use the helmetOptions configuration option.

Example:

// setup nest app and enable helmet protection
await setupNestApplication(app, {
enableHelmetProtection: true,
helmetOptions: {
// ...
}
});