Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@unifig/core

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@unifig/core

Universal, typed and validated configuration manager

  • 0.12.2-dev.11
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
941
decreased by-54.72%
Maintainers
1
Weekly downloads
 
Created
Source

Unifig

Universal, typed and validated configuration manager.

MIT Licensed NPM version Commitizen friendly codecov Build Status

Table of contents

💡 Goal

Unifig aims to provides simple and abstract way of handling app's configuration. It allows to load configuration data from multiple sources without changing defined config template. Many templates can be defined to further organize the code eg. MainConfiguration and ModuleConfiguration.

Adapted configuration data is transformed into templates and validated via class-transformer and class-validator. Once initialized configurations can be reloaded without app restart.

Installation

npm i @unifig/core
# or
yarn add @unifig/core

Setting up Templates

Unifig centralizes configuration management in classes called templates. They are resposible for deserializing config values from sources into rich js / ts objects and validating them afterwards.

import { From, Nested } from '@unifig/core';
import { Transform } from 'class-transformer';
import { IsString, IsArray } from 'class-validator';

class DbSettings {
  @From({ key: 'DB_URL', default: 'localhost' })
  @IsString()
  url: string;

  @From('DB_PASSWORD')
  @IsString()
  password: string;

  @From('DB_RECONNECT_DELAYS')
  @Transform(({ value }) => value.split(',').map((n) => Number(n)))
  @IsArray()
  reconnectDelays: number[];
}

Subtemplates

They allow to keep config structure organized by grouping inseparable properties and allowing reusing of them. The subtemplate itself is declared just as regular template, including option to nest further subtemplates in it.

export class AppSettings {
  @From('PORT')
  @IsInt()
  port: number;

  @Nested(() => DbSettings)
  db: DbSettings;
}

Loading configuration

After defining template they should be loaded before any other action in the application takes place.

import { Config, PlainConfigAdapter } from '@unifig/core';

async function bootstrap() {
  const validationError = await Config.register({
    template: AppSettings,
    adapter: new PlainConfigAdapter({
      PORT: 3000,
      DB_URL: 'localhost:5467',
      DB_PASSWORD: 'password',
      DB_RECONNECT_DELAYS: '56,98,34,72',
    }),
  });

  // OR

  const validationError = Config.registerSync({
    template: AppSettings,
    adapter: new PlainConfigAdapter({
      PORT: 3000,
      DB_URL: 'localhost:5467',
      DB_PASSWORD: 'password',
      DB_RECONNECT_DELAYS: '56,98,34,72',
    }),
  });

  if (validationError) {
    console.error(validationError.message);
    process.exit(1);
  }

  console.log(Config.getValues(AppSettings).port); // output: 3000
}

bootstrap();

Above example uses built-in adapter which transforms static object into Settings. See full list of adapters here.

Values adapters

Unifig allows to easily swap config values sources or introduce new ones. Implementation of the adapter consist of class which exposes load method, which is called upon config initialization. The method should return dictionary with keys used in @From decorators in templates and underlying values.

import { ConfigAdapter, ConfigSource } from '@unifig/core';

export class CustomAdapter implements ConfigSyncAdapter {
  load(): ConfigSource {
    return {
      PORT: '3000', // will be parsed to number as declared in template
      DB_URL: 'localhost:5467',
      DB_PASSWORD: 'password',
      DB_RECONNECT_DELAYS: '56,98,34,72',
    };
  }
}
Config.registerSync({
  template: AppSettings,
  adapter: new CustomAdapter(),
});

In case of asynchronous way of loading config (like cloud remote configuration service) the adapter needs to implement ConfigAdapter interface.

import { ConfigAdapter, ConfigSource } from '@unifig/core';

export class RemoteConfigAdapter implements ConfigAdapter {
  async load(): Promise<ConfigSource> {
    return { ... };
  }
}

Such adapter requires to be used by async register method.

await Config.register({
  template: AppSettings,
  adapter: new RemoteConfigAdapter(),
});
Types conversion

When loading configuration from predefined objects it's handy to disable the default behavior of implicit properties types conversion.

await Config.register({
  template: AppSettings,
  enableImplicitConversion: false,
  adapter: new CustomAdapter(),
});

Multiple Configurations

In case no single configuration root (AppSettings in above example), templates need to be registered separately.

await Config.register(
  { template: DbSettings, adapter: ... },
  { template: AuthSettings, adapter: ... },
  { templates: [FilesStorageSettings, CacheSettings], adapter: ... },
);

Inline validation rejection

To throw validation exception right away after encountering errors instead of returning it use

await Config.registerOrReject({ template: DbSettings, adapter: ... });

Stale Data

Upon changing application's configuration one must be usually restared to re-fetch new values. Unifig delivers an option to reload registered configurations in real time without app's restart.

await Config.getContainer(Settings).refresh();

Todo before 1.0.0 release

  • allow to automate configurations values reloads in user-defined source group scoped intervals
  • add hook for config refreshed event to allow an app react to the change. Pass difference between old and new values?
  • add example project under /examples directory

License

This project is licensed under the MIT License - see the LICENSE file for details.

Keywords

FAQs

Package last updated on 07 Feb 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc