Socket
Socket
Sign inDemoInstall

ts-configurable

Package Overview
Dependencies
23
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.2 to 0.1.0

11

CHANGELOG.md
# CHANGELOG
## 1.0.0
## 0.1.0
- Update documentation
- Additionally export IDecoratorOptions and IEnvOptions from package
- Change throwing "Error" to "TypeError"
## 0.0.2
- Update documentation
- Introduce CI tools (CircleCI, Greenkeeper, Codecov)

2

index.d.ts

@@ -1,3 +0,3 @@

export { IConstructorOptions } from './lib/interfaces';
export { IConstructorOptions, IEnvOptions, IDecoratorOptions } from './lib/interfaces';
export { Configurable } from './lib/configurable';
export { BaseConfig } from './lib/base-config';
import { DotenvConfigOptions } from 'dotenv';
/** Environment variables specific options */
interface IEnvOptions {
export interface IEnvOptions {
/** Seperator for environment variables (default: '__') */

@@ -5,0 +5,0 @@ separator?: string;

@@ -22,3 +22,3 @@ "use strict";

else {
throw new Error(`Property '${parent}.${key}' is of type object but a non-object value ('${JSON.stringify(value)}') was assigned!`);
throw new TypeError(`Property '${parent}.${key}' is of type object but a non-object value ('${JSON.stringify(value)}') was assigned!`);
}

@@ -34,3 +34,3 @@ }

else {
throw new Error(`Property '${parent}.${key}' is of type array but a non-array value ('${JSON.stringify(value)}') was assigned!`);
throw new TypeError(`Property '${parent}.${key}' is of type array but a non-array value ('${JSON.stringify(value)}') was assigned!`);
}

@@ -44,3 +44,3 @@ }

else {
throw new Error(`Property '${parent}.${key}' is of type null or undefined but a non-primitive value ('${JSON.stringify(value)}') was assigned!`);
throw new TypeError(`Property '${parent}.${key}' is of type null or undefined but a non-primitive value ('${JSON.stringify(value)}') was assigned!`);
}

@@ -55,7 +55,7 @@ }

else {
throw new Error(`Property '${parent}.${key}' is of type ${typeof templateValue} but a value of type ${typeof value} ('${JSON.stringify(value)}') was assigned!`);
throw new TypeError(`Property '${parent}.${key}' is of type ${typeof templateValue} but a value of type ${typeof value} ('${JSON.stringify(value)}') was assigned!`);
}
}
else {
throw new Error(`Property '${parent}.${key}' is of type ${typeof templateValue} but a non-primitive value ('${JSON.stringify(value)}') was assigned!`);
throw new TypeError(`Property '${parent}.${key}' is of type ${typeof templateValue} but a non-primitive value ('${JSON.stringify(value)}') was assigned!`);
}

@@ -62,0 +62,0 @@ }

{
"version": "0.0.2",
"version": "0.1.0",
"name": "ts-configurable",
"description": "",
"keywords": [],
"keywords": [
"config",
"settings",
"configuration",
"decorator",
"dotenv",
"argument",
"parser",
"environment",
"variables",
"args",
"argv",
"env"
],
"repository": {

@@ -7,0 +20,0 @@ "type": "git",

# TS-Configurable
<p align="center">
<a href="https://github.com/derbenoo/ts-configurable">
<img src="https://github.com/derbenoo/ts-configurable/raw/master/ts-configurable.svg?sanitize=true" alt="ts-configurable" width="250" />
</a>
</p>
<div align="center">
<p align="center">
[![npm](https://img.shields.io/npm/v/ts-configurable.svg?color=007acc)](https://www.npmjs.com/package/ts-configurable) [![GitHub](https://img.shields.io/github/license/derbenoo/ts-configurable.svg?color=007acc)](https://github.com/derbenoo/ts-configurable/blob/master/LICENSE) [![npm bundle size](https://img.shields.io/bundlephobia/min/ts-configurable.svg?color=007acc)](https://www.npmjs.com/package/ts-configurable)
[![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/ts-configurable.svg)](https://snyk.io/test/npm/ts-configurable) [![CircleCI (all branches)](https://img.shields.io/circleci/project/github/derbenoo/ts-configurable.svg)](https://circleci.com/gh/derbenoo/ts-configurable) [![Codecov](https://img.shields.io/codecov/c/gh/derbenoo/ts-configurable.svg)](https://codecov.io/gh/derbenoo/ts-configurable) [![Greenkeeper badge](https://badges.greenkeeper.io/derbenoo/ts-configurable.svg)](https://github.com/derbenoo/ts-configurable/blob/master/package.json)

@@ -15,2 +17,3 @@

</p>
</div>

@@ -20,4 +23,6 @@

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:
Let's be real, configuration is not sexy. We all just want to set up our project's configuration as easily as possible and then move on to build whatever we _actually_ wanted to build. But what if I told you that you can meet all your configuration needs with a single line of code and then never have to worry about it again?
Simply create a class defining all configuration properties, tack on the `@Configurable()` decorator and off you go! Take advantage of type-safety, environment variable loading, command line argument parsing and much more right out-of-the-box.
## :running: Get started

@@ -40,3 +45,3 @@

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

@@ -58,17 +63,17 @@ ```sh

$ port=random ts-node server-config.ts
Property 'ServerConfig.port' is of type number but a value of type string ('"random"') was assigned!
TypeError: Property 'ServerConfig.port' is of type number but a value of type string ('"random"') was assigned!
```
## :tada: Features
## :tada: Benefits
- Type safety for your configuration:
- No need to maintain a separate interface
- No need to maintain a separate TypeScript 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:
- Enforce correct types for values passed by environment variables and command line arguments (`strictTypeChecking` option)
- Take 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](https://www.npmjs.com/package/dotenv))
- Inherit from other configuration classes
- Enforce configuration values to be read-only at compile time ([readonly modifier](https://www.typescriptlang.org/docs/handbook/classes.html#readonly-modifier)) and at runtime (`enforceReadonly` option)
- Load environment variables from a local file (using [dotenv](https://www.npmjs.com/package/dotenv/v/6.2.0))

@@ -90,11 +95,11 @@ ## :wrench: API

##### options.enforceReadonly: `boolean`
##### options.enforceReadonly: _`boolean`_
Enforce that all properties are read-only by using `Object.freeze()` (default: true)
##### options.loadEnvFromFile: `false` | [DotenvConfigOptions](https://www.npmjs.com/package/dotenv#options)
##### options.loadEnvFromFile: _`false`_ | [DotenvConfigOptions](https://www.npmjs.com/package/dotenv/v/6.2.0#options)
Apply environment variables from a file to the current `process.env`
##### options.parseArgv: `false` | `IArgvOptions`
##### options.parseArgv: _`false`_ | `IArgvOptions`

@@ -131,7 +136,44 @@ Whether to parse command line arguments (default: true)

## Example: Nested Properties
## :ok_hand: Provide Options and Defaults via the Constructor
By extending the `BaseConfig` class, both the options passed to the `@Configurable()` decorator as well as the default values assigned to the instance properties can be overriden via the constructor during instantiation:
```ts
import { Configurable, BaseConfig } from '@tfs/config';
// server-config.ts
import { Configurable, BaseConfig } from 'ts-configurable';
@Configurable({ parseEnv: { prefix: '' } })
class ServerConfig extends BaseConfig<ServerConfig> {
host = 'localhost';
port = 3000;
}
const config = new ServerConfig({
options: {
parseEnv: false,
},
config: {
host: '0.0.0.0',
},
});
console.log(config);
```
While activating the parsing of environment variables inside the decorator options, we override this setting again in the constructor provided options and set it to `false`, therefore disabling any environment variable parsing. Additionally, we override the default value for the `host` property from `localhost` to `0.0.0.0` inside the constructor as well:
```sh
# Ignore env variable "port", override host variable via constructor
$ port=4200 ts-node server-config.ts
ServerConfig { host: '0.0.0.0', port: 3000 }
```
## :open_mouth: Nested Properties
For nested configuration properties, it is recommended to define a new type for keeping type safety:
```ts
// order-pizza.ts
import { Configurable, BaseConfig } from 'ts-configurable';
type TOrder = Partial<{

@@ -163,7 +205,7 @@ recipient: string;

By adding the `@Configurable()` decorator to any class, all of its properties can be configured via environment variables and command line arguments:
Accessing nested properties is done using the `__` separator for environment variables (can be configured via `parseEnv.separator`) and the dot notation (`.`) for command line arguments:
```sh
```
export pizza_order__delivered=false
$ start pizza-app --order.recipient=Jonny"
$ ts-node order-pizza.ts --order.recipient=Jonny"

@@ -189,17 +231,62 @@ {

## Provide options and config values via constructor
## :book: Loading Environment Variables from a File
## Negating Boolean Arguments
It can be useful during development to keep a local `.env` file containing configuration values that the developer wants to set for himself. The file is typically excluded from version control (e.g., by adding it to the `.gitignore` of the repository). When using the `@Configurable()` decorator, environment variables specified in a `.env` file located in the current working directory are loaded into `process.env` before the configuration object is created. However, another path can be specified using the `loadEnvFromFile.path` option.
This functionality is implemented using the [dotenv](https://www.npmjs.com/package/dotenv/v/6.2.0) package. You can find out more by reading the package's documentation:
- [Options](https://www.npmjs.com/package/dotenv/v/6.2.0#options)
- [Rules](https://www.npmjs.com/package/dotenv/v/6.2.0#rules)
- [FAQ](https://www.npmjs.com/package/dotenv/v/6.2.0#faq)
## :grey_exclamation: 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`.
```ts
// pay-pizza.ts
import { Configurable } from 'ts-configurable';
@Configurable()
class PizzaConfig {
cash = false;
debit = true;
paypal = true;
}
console.log(new PizzaConfig());
```
$ start pizza-app --cash --no-paypal
{ cash: true, paypal: false }
```
$ ts-node pay-pizza.ts --cash --no-paypal
{ cash: true, debit: true, paypal: false }
```
## Hierarchical atomic object merging
## :snowflake: Readonly Properties and Object Freezing
## Contributing
The ts-configurable package encourages developers to keep all configuration values static during the lifetime of the application. All sources (environment variables, command line arguments, ...) are parsed and merged during the instantiation of the configuration class object. After an object has been created, the object should be considered read-only, which can be enforced using the `enforceReadonly` option. This ensures that the configuration object is not modified at runtime (using [Object.freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)). Additionally, all class properties can be marked with the TypeScript `readonly` modifier to prevent assignments at compile time. This way, the developer gets instant feedback from his IDE if he accidentially tries to set a read-only configuration value.
Keeping all configuration values read-only after initialization has several benefits:
- The configuration object is a single source of truth, allowing all modules to have a consistent state
- The developer is assured that multiple reads of a configuration value return the same result
- The developer does not have to react to a configuration change (e.g., re-bind the webserver to a different port)
Only a restart of the application triggers a reloading of the configuration.
## :crown: Hierarchical + Partial Object Merging
The ability to specify configuration values using multiple sources (env vars, cmd args) necessitates the specification of a configuration source hierarchy. Each property assignment specified via one of the sources is always overriden by the same property assignment of a source higher in the loading hierarchy. The values specified via a source take precedence over all values specified in sources that are below in the loading hierarchy.
The configuration loading hierarchy is listed below (1 = highest, 4 = lowest):
1. Command line arguments
2. Environment variables
3. Constructor options on instantiation
4. Defaults provided with the property definitions
This behavior is implemented using the [nconf](https://www.npmjs.com/package/nconf) package. In short, each configuration source is converted into a partially filled configuration object. All those configuration objects are then merged with the precedence order listed above. This means that individual values can be set, even for nested properties!
## :pray: Contributing
You are welcome to contribute to the ts-configurable GitHub repository! All infos can be found here: [How to contribute](https://github.com/derbenoo/ts-configurable/blob/master/CONTRIBUTING.md)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc