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

@flowcore/microservice

v5.0.0

Published

The flowcore microservice library is designed to provide strong opinions on how to handle configuration, logging, health checks, metrics, and observability. It provides a set of modules that allow you to quickly set up services.

Downloads

200

Readme

Build

Flowcore Microservice

The flowcore microservice library is designed to provide strong opinions on how to handle configuration, logging, health checks, metrics, and observability. It provides a set of modules that allow you to quickly set up services.

The library is particularly well-suited for use in microservice architectures, where it can help you quickly and easily set up the essential components of configuration, logging, health checks, metrics, and observability.

Installation

install with npm:

npm install @flowcore/microservice @nestjs/core @nestjs/common @nestjs/terminus

or yarn:

yarn add @flowcore/microservice @nestjs/core @nestjs/common @nestjs/terminus

Usage

The library provides a set of modules that allow you to quickly set up services. The modules are:

Configuration

The configuration library uses zod to validate the configuration. It provides a set of primitives that can be used to create configuration schemas. The library also provides a configuration Module that can load and validate configuration from environment variables.

To use the module first create a configuration schema.

// config file
import {z} from "zod";
import {ConfigurationSchema} from "@flowcore/microservice";

export const SomeConfigurationShape = z.object({
  someKey: z.string(),
});
export type SomeConfiguration = z.infer<typeof SomeConfigurationShape>;

export class SomeConfigurationSchema extends ConfigurationSchema {
  context = "some-context";
  linking = {
    someKey: {
      env: "SOME_KEY",
      default: "some-default-value", // optional, only if you want to override the default value when loading the schema
    },
  };
  shape = SomeConfigurationShape;

  // this is optinal, but can be used to override the defaults specified in the linking
  constructor(overrideDefaults?: { [key: string]: any }) {
    super();
    ConfigurationSchema.override(this.linking, overrideDefaults);
  }
}

NB! If you want to be able to override the default of a configuration value you can use the ConfigurationSchema class to set the default, not the zod schema and include the constructor specified above.

then create a module builder that uses the configuration schema.

// module builder
import {SomeModule} from "./some.module";
import {BaseBuilder, ConfigService} from "@flowcore/microservice";

export class SomeModuleBuilder extends BaseBuilder {
  requiredContext = ["some-context"];

  override build() {
    super.build();

    if (!this.config) {
      throw new Error(`Missing config for ${this.constructor.name}`);
    }

    return SomeModule.registerAsync({
      imports: [this.config],
      inject: [ConfigService],
      useFactory: (config: ConfigService<SomeConfiguration>) => ({
        someKey: config.schema.someKey,
      }),
    });
  }
}

requiredContext is used when you want the configuration to be required. If the configuration is not provided the module will throw an error.

Then to use the builder and configuration in your service.

// app module
import {Module} from "@nestjs/common";
import {SomeModuleBuilder} from "./some-builder";
import {SomeConfigurationSchema} from "./some-config";
import {
  ConfigFactory,
  ConfigModule,
} from "@flowcore/microservice";

const config = ConfigModule.forRoot(
  new ConfigFactory()
    // ... other schemas
    .withSchema(SomeConfigurationSchema, /* optional override defaults { path-to-key: new default value, } */)
  // ... other schemas
);

@Module({
  imports: [
    config,
    // ... other modules
    new SomeModuleBuilder().withConfig(config).build(),
    // ... other modules
  ],
  controllers: [],
  providers: [],
})
export class AppModule {
}

The configuration module has a DefaultAppConfigurationSchema that will be applied unless explicitly set to false. The default configuration schema will load the following environment variables:

  • PORT - the port the service will listen on for http endpoints, for example /health and /metrics (default: 3000)

this is exported as the DefaultAppConfiguration interface in the @flowcore/microservice package. And can be used when accessing the configuration through useFactory.

Logging

The logging library uses winston and nest-winston to provide logging. It provides configuration and injection mechanics for the winston logger.

To use the module load the configuration schema into the configuration factory and import the logging module using the builder.

// app module
import {Module} from "@nestjs/common";
import {
  ConfigFactory,
  ConfigModule,
  LoggerModuleBuilder,
  LoggerModuleConfigurationSchema,
} from "@flowcore/microservice";

const config = ConfigModule.forRoot(
  new ConfigFactory()
    // ... other schemas
    .withSchema(LoggerModuleConfigurationSchema),
  // ... other schemas
);

@Module({
  imports: [
    config,
    // ... other modules
    new LoggerModuleBuilder().withConfig(config).build(),
    // ... other modules
  ],
  controllers: [],
  providers: [],
})
export class AppModule {
}

the logging module will load the following environment variables:

  • LOG_LEVEL - the log level to use for the logger (default: info)
  • LOG_PRETTY_PRINT - whether to pretty print the logs (default: false)
  • LOG_USE_LABELS - whether to use labels in the logs (default: false)

this is exported as the LoggerModuleConfiguration interface in the @flowcore/microservice package. And can be used when accessing the configuration through useFactory.

Health

The health module uses @nestjs/terminus to provide health checks. It provides decorator that can be used to collect health checks.

to use the module, first create a health controller.

// health controller
import {Controller, Get} from "@nestjs/common";
import {HealthCheck, HealthCheckResult} from "@nestjs/terminus";
import {HealthService} from "@flowcore/microservice";

@Controller("health")
export class HealthController {
  constructor(private health: HealthService) {
  }

  @Get()
  @HealthCheck()
  async check(): Promise<HealthCheckResult> {
    return this.health.check();
  }
}

Remember to add an access decorator to the health check endpoint if you are using authentication in your application.

Then import it and the HealthModule into your application module.

// app module
import {Module} from "@nestjs/common";
import {
  ConfigFactory,
  ConfigModule,
  HealthModuleBuilder,
} from "@flowcore/microservice";
import {HealthController} from "./health.controller";

@Module({
  imports: [
    new HealthModuleBuilder().usingController(HealthController).build(),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {
}

Then to add health checks to the service, use the @HealthCheckIndicator decorator.

// some health check
import {HealthCheckIndicator, CheckHealth} from "@flowcore/microservice";
import {Injectable} from "@nestjs/common";
import {HealthIndicator, HealthIndicatorResult} from "@nestjs/terminus";

@Injectable()
@HealthCheckIndicator()
class HealthyService extends HealthIndicator implements CheckHealth {
  async isHealthy(): Promise<HealthIndicatorResult> {
    // do some health check logic
    return this.getStatus(/* some key */, /* true or false */);
  }
}

Remember to add the HealthModule to the module imports.

Metrics

The metrics module is a wrapper around @willsoto/nestjs-prometheus to provide metrics for the service. It provides a module that can be configured and imported into the application module.

To use the module, first create a metrics controller.

// metrics controller
import {Controller, Get, Res} from "@nestjs/common";
import {PrometheusController} from "@flowcore/microservice";
import {Response} from "express";

@Controller()
export class MetricsController extends PrometheusController {
  @Get()
  async index(@Res() response: Response) {
    return super.index(response);
  }
}

Then import it and the MetricsModule into your application module using the builder.

// app module
import {Module} from "@nestjs/common";
import {MetricsController} from "./metrics.controller";
import {MetricsModuleBuilder} from "@flowcore/microservice";

@Module({
  imports: [
    // ... other modules
    new MetricsModuleBuilder().usingController(MetricsController).build()
    // ... other modules
  ],
  controllers: [],
  providers: [],
})
export class AppModule {
}

to use the metrics module, follow the instructions in the @willsoto/nestjs-prometheus package.

The createCounterProvider and the Counter class are exported from the @flowcore/microservice package, same goes for Gauge,Histogram andSummary. So you can import them from there instead of the @willsoto/nestjs-prometheus and prom-client packages.

To use default node metrics exported from the @willsoto/nestjs-prometheus package, use the withDefaultMetrics method when building the metrics module.

To add default labels to all metrics, use the withDefaultLabels method when building the metrics module.

Observability (Deprecated)

the observability module has been marked as deprecated, and will be implemented in a new version using Open Telemetry. For now, traces are implemented using eBPF from Groundcover.