JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 311
  • Score
    100M100P100Q85112F
  • License MIT

Package Exports

  • ts-configurable

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ts-configurable) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

ts-configurable

TS-Configurable

Make all properties of a class configurable using only one decorator!

TS-Configurable implements the @Configurable() decorator to make any class configurable via environment variables and command line arguments! Additionally, the BaseConfig<T> class can be extended to allow the passing of an options (options: Partial<T>) object that can partially override the property defaults specified in the configuration class:

🏃 Get started

Install via npm i ts-configurable and create a config class with default values for each property:

// server-config.ts
import { Configurable } from 'ts-configurable';

@Configurable()
class ServerConfig {
  host = 'localhost';
  port = 3000;
}

console.log(new ServerConfig());

Due to the @Configurable() decorator, the values for all properties can now be set via environment variables and command line arguments:

# Default config instance
$ ts-node server-config.ts
ServerConfig { host: 'localhost', port: 3000 }

# Change port via command line argument
$ ts-node server-config.ts --port=4200
ServerConfig { host: 'localhost', port: 4200 }

# Change host via environment variable
$ host=0.0.0.0 ts-node server-config.ts
ServerConfig { host: '0.0.0.0', port: 3000 }

# Throw an error if a value with a different type was assigned
$ port=random ts-node server-config.ts
Property 'ServerConfig.port' is of type number but a value of type string ('"random"') was assigned!

🎉 Features

  • Type safety for your configuration:
    • No need to maintain a separate interface
    • Types can be infered from the property's default value
    • Enforce correct types for values passed by environment variables and command line arguments
  • Take full advantage of having a configuration class:
    • Calculate config values based on other config values (e.g. url from host and port)
    • Getter functions (e.g. get debugPort() { return this.port + 1000; })
    • Inherit from other (config) classes
  • Enforce the configuration object to be read-only
  • Load environment variables from a local file (using dotenv)

🔧 API

@Configurable([options])

Configurable(options?: IDecoratorOptions)

Class decorator for marking a class configurable: The values of all class properties can be set using the following sources, listed by priority (1 = highest):

  1. Command line arguments
  2. Environment variables
  3. Constructor options on instantiation
  4. Defaults provided with the property definitions

The final values for the config instance's properties are calculated upon instantiation.

<Optional> options.enforceReadonly: boolean

Enforce that all properties are read-only by using Object.freeze() (default: true)

<Optional> options.loadEnvFromFile: false | DotenvConfigOptions

Apply environment variables from a file to the current process.env

<Optional> options.parseArgv: false | IArgvOptions

Whether to parse command line arguments (default: true)

<Optional> options.parseArgv.prefix: string

Prefix for command line arguments (default: no prefix)

<Optional> options.parseEnv: false | IEnvOptions

Whether to parse environment variables (default: true)

<Optional> options.parseEnv.lowerCase: boolean

Whether to lower-case environment variables (default: false)

<Optional> options.parseEnv.prefix: string

Prefix for environment variables (default: no prefix)

<Optional> options.parseEnv.separator: string

Seperator for environment variables (default: '__')

<Optional> options.parseValues: boolean

Attempt to parse well-known values (e.g. 'false', 'null', 'undefined' and JSON values) into their proper types (default: true)

<Optional> options.strictTypeChecking: boolean

Throw an error if a config entry is set to a value of a different type than the default value (e.g. assigning a number to a string property) (default: true)

Example: Nested Properties

import { Configurable, BaseConfig } from '@tfs/config';

type TOrder = Partial<{
  recipient: string;
  priceTotal: number;
  delivered: boolean;
  billing: Partial<{ address: string }>;
}>;

class BasePizzaConfig extends BaseConfig<BasePizzaConfig> {
  id = 5;
  topping = 'cheese';
  rating = null;
  ingredients = ['tomato', 'bread'];
  order: TOrder = {
    recipient: 'John Doe',
    priceTotal: 6.2,
    delivered: true,
    billing: {
      address: 'Jerkstreet 53a, 1234 Whatevertown',
    },
  };
}

const pizzaConfig = new PizzaConfig({ topping: 'bacon' });
console.log(JSON.stringify(pizzaConfig, null, 2));

By adding the @Configurable() decorator to any class, all of its properties can be configured via environment variables and command line arguments:

export pizza_order__delivered=false
$ start pizza-app --order.recipient=Jonny"

{
  "id": 5,
  "topping": "bacon",
  "rating": null,
  "ingredients": [
    "tomato",
    "bread"
  ],
  "order": {
    "recipient": "Jonny",
    "priceTotal": 6.2,
    "delivered": false,
    "billing": {
      "address": "Jerkstreet 53a, 1234 Whatevertown"
    }
  }
}

Negating Boolean Arguments

If you want to explicitly set a field to false instead of just leaving it undefined or to override a default you can add a no- before the key: --no-key.

$ start pizza-app --cash --no-paypal
{ cash: true, paypal: false }

Hierarchical atomic object merging

Provide options and config values via constructor

Test Coverage