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

@monkee/turbo-config

v2.0.0

Published

turbo-ts-config package

Downloads

688

Readme

Turbo config

npm version

Complete configuration solution for typescript codebases.

Main features

  1. Yaml, env, cli config sources with priority configuration and overriding
  2. Typed, class-based
  3. JSON schema generation for yaml autocompletion and validation in editors and IDEs
  4. Documentation generator for yaml and env variables
  5. Built on the top of the mature community driven libraries:

Example

@ConfigPrefix('app')
class AppConfig {
  // Simple field
  @ConfigField({ optional: true })
  httpPort?: number;

  // Nested config
  @ConfigField({ nested: true })
  db!: DbConfig;

  // Sources overriding. Arrays support
  @ConfigField({
    arrayOf: 'strings',
    yamlKey: 'services.manager.tasks',
    cliKey: 'servicesList',
    arraySeparator: ':',
  })
  tasks!: string[];
}

class DbConfig {
  @ConfigField()
  host!: string;

  @ConfigField()
  port: number = 3306;

  @ConfigField()
  autoReconnect = true;
}

Table of contents

Getting Started

Prerequisites

This library depends on decorators, so make sure your tsconfig.json includes this settings:

"compilerOptions": {
  "experimentalDecorators": true,
  "emitDecoratorMetadata": true
}

Installation

Install via npm

npm i @monkee/turbo-config

Basic usage

import { Transform } from 'class-transformer';
import { IsNumber } from 'class-validator';
import { buildConfig, ConfigField } from '@monkee/turbo-config';

class AppConfig {
  /*
    Every field with this decorator will be parsed as config field.
    By default keys will be inferred from property name:
    APP_PORT=3000 for env
    appPort: 3000 yaml
    --appPort=3000 for cli
  */
  @ConfigField()
  @Min(0)
  @Max(65535)
  appPort: number = 3000;
  /*
    NOTE: due reflect-metadata limitation you should specity property type
    with default value. Othervise library won't infer type and the magic won't work.
    Use ignoreProperties flag with no-inferrable-types eslint rule if necessary
  */

  /*
    There are some transforms and validations under the hood by default.
    parseFloat() and isNumber() validator for numbers for example.
    Its possible to disable everyting and handle it manually.
    Any features of ClassValidator and ClassTransformer is available.
  */
  @ConfigField({
    disableDefaultDecorators: true,
  })
  @Transform(({ value }) => parseFloat(value))
  @IsNumber()
  redisPort!: number;

  /*
    You can override any source key
  */
  @ConfigField({
    envKey: 'SUPER_APP_HOST',
    yamlKey: 'super.app.host',
    cliKey: 'cli.app.host',
  })
  appHost!: string;

  // Array example. Due to reflection limitation you should specify type
  @ConfigField({ arrayOf: 'ints' })
  intsArray: number[] = [1, 2, 3];
}

const main = async () => {
  const { config } = await buildConfig(AppConfig, {
    ymlFiles: ['config.yml', 'override.yml'],
  });

  console.log(config);
};

Documentation and json schema generators

import { generateConfigDoc, ConfigPrefix, ConfigField } from '@monkee/turbo-config';
import * as fs from 'fs/promises';

@ConfigPrefix('nest')
class AppConfig {
  @ConfigField()
  port!: number;
}

const main = async () => {
  const { jsonSchema } = await buildConfig(AppConfig);

  // save config reference to file
  await generateConfigDoc(jsonSchema, {
    // you can also use return value of generateConfigDoc to manually write file
    writeToFile: 'CONFIG_REFERENCE.md',
  });

  // write json schema to file
  fs.writeFile('config-schema.json', JSON.stringify(jsonSchema, null, 2), 'utf-8');
};

In your yml config file you can include generated json schema. Supported in VSCode and IDEA (Webstorm).

# yaml-language-server: $schema=config-schema.json

nest:
  port: 3000

Advanced usage

Nested configs

import { buildConfig, ConfigField } from '@monkee/turbo-config';

class Nested {
  @ConfigField()
  port = 3000;

  @ConfigField()
  autoReconnect = true;
}

class AppConfig {
  @ConfigField({ nested: true })
  nested!: Nested;
}

const main = async () => {
  const { config } = await buildConfig(AppConfig);

  console.log(config.nested);
};

Array of non-primitive types

import { buildConfig, ConfigField } from '@monkee/turbo-config';

class Repository {
  @ConfigField()
  url!: string;

  @ConfigField()
  token!: string;
}

class AppConfig {
  @ConfigField({ arrayOf: Repository })
  repositories!: Repository[];
}

const main = async () => {
  process.env.REPOSITORIES = 'url=first;token=someToken,url=second;token=secret';

  const { config } = await buildConfig(AppConfig);

  console.log(config.repositories);
};

Build options reference

// Default build options
{
  sourcesPriority: [CONFIG_SOURCE.YAML, CONFIG_SOURCE.ENV, CONFIG_SOURCE.CLI],
  throwOnValidationError: true,
  throwIfYmlNotExist: false,
  throwIfEnvFileNotExist: false,
  ymlFiles: [],
  envFiles: [],
  loadEnvFiles: false,
  classValidatorOptions: {
    skipMissingProperties: false,
  },
  classTransformerOptions: {
    exposeDefaultValues: true,
  },
}

Error handling

const main = async () => {
  // manually handle validation errors
  const { config, validationErrors } = await buildConfig(AppConfig, {
    throwOnValidationError: false,
  });

  throw new Error(validationErrors);
};

Authors

Vlad Boroda - Initial work - Enity