@unifig/core
Advanced tools
Comparing version 0.6.0 to 0.7.0
@@ -1,2 +0,2 @@ | ||
export * from './config-adapter.interface'; | ||
export * from './plain.adapter'; | ||
export * from './adapter'; | ||
export * from './plain'; |
@@ -17,3 +17,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./config-adapter.interface"), exports); | ||
__exportStar(require("./plain.adapter"), exports); | ||
__exportStar(require("./adapter"), exports); | ||
__exportStar(require("./plain"), exports); |
@@ -5,6 +5,10 @@ export * from './adapters'; | ||
export * from './validator'; | ||
import { ConfigManager } from './manager'; | ||
import { ConfigContainer } from './manager'; | ||
/** | ||
* @deprecated Will be removed in v1.0.0. Renamed to `ConfigContainer`. | ||
*/ | ||
export type IConfigContainer<TTemplate extends Record<string, any>> = ConfigContainer<TTemplate>; | ||
/** | ||
* Global ConfigManager instance. | ||
*/ | ||
export declare const Config: ConfigManager; | ||
export declare const Config: import("./manager").ConfigManager; |
@@ -22,6 +22,6 @@ "use strict"; | ||
__exportStar(require("./validator"), exports); | ||
const manager_1 = require("./manager"); | ||
const manager_factory_1 = require("./manager/manager.factory"); | ||
/** | ||
* Global ConfigManager instance. | ||
*/ | ||
exports.Config = new manager_1.ConfigManager(); | ||
exports.Config = manager_factory_1.ConfigManagerFactory.create(); |
export declare const mappedPropertyKey: (key: string) => string; | ||
export declare const PROPERTIES_MAPPING_METADATA = "__unifigPropertiesMapping__"; | ||
export declare const PROPERTIES_NESTING_METADATA = "__unifigPropertiesNesting___"; | ||
export declare const PROPERTIES_MAPPING_METADATA: unique symbol; | ||
export declare const PROPERTIES_NESTING_METADATA: unique symbol; |
@@ -6,3 +6,3 @@ "use strict"; | ||
exports.mappedPropertyKey = mappedPropertyKey; | ||
exports.PROPERTIES_MAPPING_METADATA = '__unifigPropertiesMapping__'; | ||
exports.PROPERTIES_NESTING_METADATA = '__unifigPropertiesNesting___'; | ||
exports.PROPERTIES_MAPPING_METADATA = Symbol('unifigPropertiesMapping'); | ||
exports.PROPERTIES_NESTING_METADATA = Symbol('unifigPropertiesNesting'); |
@@ -1,2 +0,2 @@ | ||
import { Type } from '../../utils/type.interface'; | ||
import { ClassConstructor } from '../../utils/class-constructor.interface'; | ||
/** | ||
@@ -6,3 +6,6 @@ * @deprecated Support for passing subtemplate class directly will be removed in v1.0.0. Instead, pass a factory function: `@Nested(() => SubClass)`. This is because of `SubClass` reference being undefined when parent and child templates reference each other in a circular way. | ||
*/ | ||
export declare function Nested<T>(type: Type<T>): PropertyDecorator; | ||
export declare function Nested<T>(type: () => Type<T>): PropertyDecorator; | ||
export declare function Nested<T>(type: ClassConstructor<T>): PropertyDecorator; | ||
/** | ||
* Defines subtemplate to use. | ||
*/ | ||
export declare function Nested<T>(type: () => ClassConstructor<T>): PropertyDecorator; |
@@ -1,5 +0,5 @@ | ||
import { Type } from '../utils/type.interface'; | ||
export declare type PropertySource = string; | ||
export declare type PropertyTarget = string; | ||
export declare type PropertiesMapping = Map<PropertyTarget, PropertySource>; | ||
export declare type PropertiesNesting = Map<PropertyTarget, () => Type>; | ||
import { ClassConstructor } from '../utils/class-constructor.interface'; | ||
export type PropertySource = string; | ||
export type PropertyTarget = string; | ||
export type PropertiesMapping = Map<PropertyTarget, PropertySource>; | ||
export type PropertiesNesting = Map<PropertyTarget, () => ClassConstructor>; |
@@ -1,1 +0,1 @@ | ||
export * from './config.container.interface'; | ||
export * from './container'; |
@@ -17,2 +17,2 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./config.container.interface"), exports); | ||
__exportStar(require("./container"), exports); |
@@ -1,5 +0,5 @@ | ||
import { Type } from '../../utils/type.interface'; | ||
import { UnifigException } from '../../exceptions/unifig.exception'; | ||
import { ClassConstructor } from '../../utils/class-constructor.interface'; | ||
export declare class ConfigNotInitializedException extends UnifigException { | ||
constructor(template: Type); | ||
constructor(template: ClassConstructor); | ||
} |
export * from './container'; | ||
export * from './exceptions'; | ||
export * from './config.manager'; | ||
export * from './config.manager.options'; | ||
export * from './manager.factory'; | ||
export * from './manager.options'; | ||
export * from './manager'; |
@@ -19,3 +19,4 @@ "use strict"; | ||
__exportStar(require("./exceptions"), exports); | ||
__exportStar(require("./config.manager"), exports); | ||
__exportStar(require("./config.manager.options"), exports); | ||
__exportStar(require("./manager.factory"), exports); | ||
__exportStar(require("./manager.options"), exports); | ||
__exportStar(require("./manager"), exports); |
@@ -1,5 +0,5 @@ | ||
export declare type DeepReadonly<T> = T extends (infer R)[] ? DeepReadonlyArray<R> : T extends Function ? T : T extends object ? DeepReadonlyObject<T> : T; | ||
export type DeepReadonly<T> = T extends (infer R)[] ? DeepReadonlyArray<R> : T extends Function ? T : T extends object ? DeepReadonlyObject<T> : T; | ||
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> { | ||
} | ||
declare type DeepReadonlyObject<T> = { | ||
type DeepReadonlyObject<T> = { | ||
readonly [P in keyof T]: DeepReadonly<T[P]>; | ||
@@ -6,0 +6,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
export * from './config.validation.exception'; | ||
export * from './errors'; |
@@ -17,2 +17,2 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./config.validation.exception"), exports); | ||
__exportStar(require("./errors"), exports); |
{ | ||
"name": "@unifig/core", | ||
"version": "0.6.0", | ||
"version": "0.7.0", | ||
"description": "Universal, typed and validated configuration manager", | ||
@@ -32,5 +32,5 @@ "keywords": [ | ||
"devDependencies": { | ||
"@types/validator": "^13.7.7", | ||
"@types/validator": "^13.7.10", | ||
"class-transformer": "^0.5.1", | ||
"class-validator": "^0.13.2", | ||
"class-validator": "^0.14.0", | ||
"reflect-metadata": "^0.1.13" | ||
@@ -44,6 +44,3 @@ }, | ||
}, | ||
"dependencies": { | ||
"table": "^6.8.0" | ||
}, | ||
"gitHead": "8924e03fc9ce192bf4746e84b5334f16ab2553f5" | ||
"gitHead": "8bc3b487a11a717e789734f973255dbf896fa188" | ||
} |
122
README.md
@@ -17,6 +17,9 @@ <h1 align="center">Unifig</h1> | ||
- [Goal](#goal) | ||
- [Installation](#installation) | ||
- [Quick Start](#quick_start) | ||
- [Multiple Configurations](#multiple_configurations) | ||
- [Setting up Templates](#templates) | ||
- [Subtemplates](#templates_subtemplates) | ||
- [Loading](#loading) | ||
- [Values Adapters](#loading_adapters) | ||
- [Multiple Configurations](#loading_multiple_configurations) | ||
- [Inline Validation Rejection](#loading_inline_rejection) | ||
- [Stale Data](#stale_data) | ||
@@ -44,6 +47,8 @@ - [Todo Before 1.0.0](#100todo) | ||
## Quick Start | ||
## Setting up Templates | ||
<a name="quick_start"></a> | ||
<a name="templates"></a> | ||
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. | ||
```ts | ||
@@ -55,20 +60,29 @@ import { From, Nested } from '@unifig/core'; | ||
class DbSettings { | ||
@From('global.dbUrl') | ||
@From({ key: 'DB_URL', default: 'localhost' }) | ||
@IsString() | ||
url: string; | ||
@From('global.dbPassword') | ||
@From('DB_PASSWORD') | ||
@IsString() | ||
password: string; | ||
@From('DB_RECONNECT_DELAYS') | ||
@Transform(({ value }) => value.split(',').map((n) => Number(n))) | ||
@IsArray() | ||
reconnectDelays: number[]; | ||
} | ||
``` | ||
export class Settings { | ||
@From('local.port') | ||
### Subtemplates | ||
<a name="templates_subtemplates"></a> | ||
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. | ||
```ts | ||
export class AppSettings { | ||
@From('PORT') | ||
@IsInt() | ||
port: number; | ||
@Transform(({ value }) => value.split(',').map((n) => Number(n))) | ||
@IsArray() | ||
intervals: number[]; | ||
@Nested(() => DbSettings) | ||
@@ -79,2 +93,8 @@ db: DbSettings; | ||
## Loading configuration | ||
<a name="loading"></a> | ||
After defining template they should be loaded before any other action in the application takes place. | ||
```ts | ||
@@ -84,12 +104,18 @@ import { Config, PlainConfigAdapter } from '@unifig/core'; | ||
async function bootstrap() { | ||
await Config.register({ | ||
template: Settings, | ||
const validationError = await Config.register({ | ||
template: AppSettings, | ||
adapter: new PlainConfigAdapter({ | ||
local: { port: 3000 }, | ||
global: { dbUrl: 'localhost:5467', dbPassword: 'password' }, | ||
intervals: '56,98,34,72', | ||
PORT: 3000, | ||
DB_URL: 'localhost:5467', | ||
DB_PASSWORD: 'password', | ||
DB_RECONNECT_DELAYS: '56,98,34,72', | ||
}), | ||
}); | ||
console.log(Config.getValues(Settings).port); // output: 3000 | ||
if (validationError) { | ||
console.error(validationError.message); | ||
process.exit(1); | ||
} | ||
console.log(Config.getValues(AppSettings).port); // output: 3000 | ||
} | ||
@@ -102,23 +128,55 @@ | ||
## Multiple Configurations | ||
### Values adapters | ||
<a name="multiple_configurations"></a> | ||
<a name="loading_adapters"></a> | ||
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. | ||
```ts | ||
async function bootstrap() { | ||
await Config.register( | ||
{ template: Settings, adapter: ... }, | ||
{ template: AnotherSettings, adapter: ... }, | ||
{ templates: [MoreAnotherSettings, YetMoreAnotherSettings], adapter: ... }, | ||
); | ||
import { ConfigAdapter, ConfigSource } from '@unifig/core'; | ||
config.log(Config.getValues(Settings).someProperty) | ||
config.log(Config.getValues(AnotherSettings).someProperty) | ||
config.log(Config.getValues(MoreAnotherSettings).someProperty) | ||
config.log(Config.getValues(YetMoreAnotherSettings).someProperty) | ||
export class CustomAdapter implements ConfigAdapter { | ||
async load(): Promise<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', | ||
}; | ||
} | ||
} | ||
``` | ||
Additional configs may be registered with separate `.register()` calls. | ||
```ts | ||
await Config.register({ | ||
template: AppSettings, | ||
adapter: new CustomAdapter(), | ||
}); | ||
``` | ||
### Multiple Configurations | ||
<a name="loading_multiple_configurations"></a> | ||
In case no single configuration root (`AppSettings` in above example), templates need to be registered separately. | ||
```ts | ||
await Config.register( | ||
{ template: DbSettings, adapter: ... }, | ||
{ template: AuthSettings, adapter: ... }, | ||
{ templates: [FilesStorageSettings, CacheSettings], adapter: ... }, | ||
); | ||
``` | ||
### Inline validation rejection | ||
<a name="loading_inline_rejection"></a> | ||
To throw validation exception right away after encountering errors instead of returning it use | ||
```ts | ||
await Config.registerOrReject({ template: DbSettings, adapter: ... }); | ||
``` | ||
## Stale Data | ||
@@ -125,0 +183,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
46180
4
85
854
199
1
- Removedtable@^6.8.0
- Removedajv@8.17.1(transitive)
- Removedansi-regex@5.0.1(transitive)
- Removedansi-styles@4.3.0(transitive)
- Removedastral-regex@2.0.0(transitive)
- Removedcolor-convert@2.0.1(transitive)
- Removedcolor-name@1.1.4(transitive)
- Removedemoji-regex@8.0.0(transitive)
- Removedfast-deep-equal@3.1.3(transitive)
- Removedfast-uri@3.0.3(transitive)
- Removedis-fullwidth-code-point@3.0.0(transitive)
- Removedjson-schema-traverse@1.0.0(transitive)
- Removedlodash.truncate@4.4.2(transitive)
- Removedrequire-from-string@2.0.2(transitive)
- Removedslice-ansi@4.0.0(transitive)
- Removedstring-width@4.2.3(transitive)
- Removedstrip-ansi@6.0.1(transitive)
- Removedtable@6.8.2(transitive)