mesh-config 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/out/main/config.d.ts +49 -0
- package/out/main/config.js +113 -0
- package/out/main/config.js.map +1 -0
- package/out/main/index.d.ts +1 -0
- package/out/main/index.js +2 -0
- package/out/main/index.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Configuration Microframework
|
|
2
|
+
|
|
3
|
+
Declarative configuration microframework for [Mesh IoC](https://github.com/MeshIoC/mesh-ioc).
|
|
4
|
+
|
|
5
|
+
## Highlights
|
|
6
|
+
|
|
7
|
+
- 🗜 Tidy and compact
|
|
8
|
+
- 💻 Works in browser
|
|
9
|
+
- 🔬 Strongly typed and introspectable
|
|
10
|
+
- 🌳 Ergonomic
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
1. Define and use configs in your classes:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
export class MyDatabase {
|
|
18
|
+
@config() DATABASE_USERNAME!: string;
|
|
19
|
+
@config() DATABASE_PASSWORD!: string;
|
|
20
|
+
@config({ default: 10 }) DATABASE_MAX_CONNECTIONS!: number;
|
|
21
|
+
|
|
22
|
+
async connect() {
|
|
23
|
+
await this.db.connect({
|
|
24
|
+
username: this.DATABASE_USERNAME,
|
|
25
|
+
password: this.DATABASE_PASSWORD,
|
|
26
|
+
maxConnections: this.DATABASE_MAX_CONNECTIONS,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
2. Define `Config` provider in Mesh:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
mesh.service(MyDatabase);
|
|
36
|
+
mesh.service(Config, ProcessEnvConfig);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
3. Now `DATABASE_*` values will be read from `process.env`.
|
|
40
|
+
|
|
41
|
+
4. Enjoy!
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Mesh } from 'mesh-ioc';
|
|
2
|
+
export declare const CONFIG_REF: unique symbol;
|
|
3
|
+
export type ConfigType = string | boolean | number;
|
|
4
|
+
export type ConfigParser<T> = (str: string) => T | null;
|
|
5
|
+
export type ConfigTypeCtor<T extends ConfigType> = T extends string ? typeof String : T extends number ? typeof Number : T extends boolean ? typeof Boolean : never;
|
|
6
|
+
export interface ConfigDecl {
|
|
7
|
+
key: string;
|
|
8
|
+
type: ConfigTypeCtor<any>;
|
|
9
|
+
defaultValue?: string;
|
|
10
|
+
prototype: any;
|
|
11
|
+
}
|
|
12
|
+
export interface ConfigOptions {
|
|
13
|
+
default?: ConfigType;
|
|
14
|
+
}
|
|
15
|
+
export declare function config(options?: ConfigOptions): (prototype: any, key: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Returns all `@config()` declared in class and its ancestors.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getClassConfigs(classOrProto: any): ConfigDecl[];
|
|
20
|
+
/**
|
|
21
|
+
* Returns all `@config()` declarations for all classes bound to the container.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getMeshConfigs(mesh: Mesh): ConfigDecl[];
|
|
24
|
+
/**
|
|
25
|
+
* Provides actual configuration values. Implementations must specify `resolve`.
|
|
26
|
+
*/
|
|
27
|
+
export declare abstract class Config {
|
|
28
|
+
abstract resolve(key: string): string | null;
|
|
29
|
+
static parsers: {
|
|
30
|
+
[key: string]: ConfigParser<ConfigType>;
|
|
31
|
+
};
|
|
32
|
+
getOrNull<T extends ConfigType>(key: string, type: ConfigTypeCtor<T>, defaultValue?: string | T): T | null;
|
|
33
|
+
get<T extends ConfigType>(key: string, type: ConfigTypeCtor<T>, defaultValue?: string | T): T;
|
|
34
|
+
hasKey(key: string): boolean;
|
|
35
|
+
getString(key: string, defaultValue?: string): string;
|
|
36
|
+
getNumber(key: string, defaultValue?: string | number): number;
|
|
37
|
+
getBoolean(key: string, defaultValue?: string | boolean): boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare class MapConfig extends Config {
|
|
40
|
+
map: Map<string, string>;
|
|
41
|
+
constructor(entries?: Iterable<readonly [string, string | null | undefined]>);
|
|
42
|
+
resolve(key: string): string | null;
|
|
43
|
+
}
|
|
44
|
+
export declare class ProcessEnvConfig extends MapConfig {
|
|
45
|
+
constructor();
|
|
46
|
+
}
|
|
47
|
+
export declare class ConfigError extends Error {
|
|
48
|
+
name: string;
|
|
49
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Mesh, MESH_REF } from 'mesh-ioc';
|
|
2
|
+
import { addClassMetadata, getClassMetadata } from 'reflect-utils';
|
|
3
|
+
export const CONFIG_REF = Symbol('mesh:CONFIG_REF');
|
|
4
|
+
export function config(options = {}) {
|
|
5
|
+
return (prototype, key) => {
|
|
6
|
+
const type = Reflect.getMetadata('design:type', prototype, key);
|
|
7
|
+
if (![String, Boolean, Number].includes(type)) {
|
|
8
|
+
throw new ConfigError('@config can only be used with string, number or boolean types');
|
|
9
|
+
}
|
|
10
|
+
const defaultValue = options.default == null ? undefined : String(options.default);
|
|
11
|
+
addClassMetadata(CONFIG_REF, prototype, { key, type, defaultValue, prototype });
|
|
12
|
+
Object.defineProperty(prototype, key, {
|
|
13
|
+
get() {
|
|
14
|
+
const mesh = this[MESH_REF];
|
|
15
|
+
if (!(mesh instanceof Mesh)) {
|
|
16
|
+
throw new ConfigError(`Could not read @config: ${prototype.constructor.name} not connected to Mesh`);
|
|
17
|
+
}
|
|
18
|
+
const config = mesh.resolve(Config);
|
|
19
|
+
return config.get(key, type, defaultValue);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns all `@config()` declared in class and its ancestors.
|
|
26
|
+
*/
|
|
27
|
+
export function getClassConfigs(classOrProto) {
|
|
28
|
+
const target = classOrProto instanceof Function ? classOrProto.prototype : classOrProto;
|
|
29
|
+
return getClassMetadata(CONFIG_REF, target);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns all `@config()` declarations for all classes bound to the container.
|
|
33
|
+
*/
|
|
34
|
+
export function getMeshConfigs(mesh) {
|
|
35
|
+
const result = [];
|
|
36
|
+
for (const binding of mesh.bindings.values()) {
|
|
37
|
+
if (binding.type === 'service') {
|
|
38
|
+
const configs = getClassConfigs(binding.class);
|
|
39
|
+
result.push(...configs);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result.sort((a, b) => a.key > b.key ? 1 : -1);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Provides actual configuration values. Implementations must specify `resolve`.
|
|
46
|
+
*/
|
|
47
|
+
export class Config {
|
|
48
|
+
getOrNull(key, type, defaultValue) {
|
|
49
|
+
const str = this.resolve(key) ?? defaultValue;
|
|
50
|
+
const parser = Config.parsers[type.name];
|
|
51
|
+
return str == null ? null : parser(String(str));
|
|
52
|
+
}
|
|
53
|
+
get(key, type, defaultValue) {
|
|
54
|
+
const val = this.getOrNull(key, type, defaultValue);
|
|
55
|
+
if (val == null) {
|
|
56
|
+
throw new ConfigError(`Configuration ${key} is missing`);
|
|
57
|
+
}
|
|
58
|
+
return val;
|
|
59
|
+
}
|
|
60
|
+
hasKey(key) {
|
|
61
|
+
return this.resolve(key) != null;
|
|
62
|
+
}
|
|
63
|
+
getString(key, defaultValue) {
|
|
64
|
+
return this.get(key, String, defaultValue);
|
|
65
|
+
}
|
|
66
|
+
getNumber(key, defaultValue) {
|
|
67
|
+
return this.get(key, Number, defaultValue);
|
|
68
|
+
}
|
|
69
|
+
getBoolean(key, defaultValue) {
|
|
70
|
+
return this.get(key, Boolean, defaultValue);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
Config.parsers = {
|
|
74
|
+
String: parseString,
|
|
75
|
+
Number: parseNumber,
|
|
76
|
+
Boolean: parseBoolean,
|
|
77
|
+
};
|
|
78
|
+
export class MapConfig extends Config {
|
|
79
|
+
constructor(entries = []) {
|
|
80
|
+
super();
|
|
81
|
+
this.map = new Map();
|
|
82
|
+
for (const [k, v] of entries) {
|
|
83
|
+
if (v != null) {
|
|
84
|
+
this.map.set(k, v);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
resolve(key) {
|
|
89
|
+
return this.map.get(key) ?? null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export class ProcessEnvConfig extends MapConfig {
|
|
93
|
+
constructor() {
|
|
94
|
+
super(Object.entries(process.env));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function parseString(str) {
|
|
98
|
+
return str;
|
|
99
|
+
}
|
|
100
|
+
function parseNumber(str) {
|
|
101
|
+
const num = Number(str);
|
|
102
|
+
return isNaN(num) ? null : num;
|
|
103
|
+
}
|
|
104
|
+
function parseBoolean(str) {
|
|
105
|
+
return str === 'true';
|
|
106
|
+
}
|
|
107
|
+
export class ConfigError extends Error {
|
|
108
|
+
constructor() {
|
|
109
|
+
super(...arguments);
|
|
110
|
+
this.name = this.constructor.name;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/main/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAoBpD,MAAM,UAAU,MAAM,CAAC,UAAyB,EAAE;IAC9C,OAAO,CAAC,SAAc,EAAE,GAAW,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QAChE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC3C,MAAM,IAAI,WAAW,CAAC,+DAA+D,CAAC,CAAC;SAC1F;QACD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnF,gBAAgB,CAAa,UAAU,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5F,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE;YAClC,GAAG;gBACC,MAAM,IAAI,GAAI,IAAY,CAAC,QAAQ,CAAS,CAAC;gBAC7C,IAAI,CAAC,CAAC,IAAI,YAAY,IAAI,CAAC,EAAE;oBACzB,MAAM,IAAI,WAAW,CAAC,2BAA2B,SAAS,CAAC,WAAW,CAAC,IAAI,wBAAwB,CAAC,CAAC;iBACxG;gBACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACpC,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;YAC/C,CAAC;SACJ,CAAC,CAAC;IACP,CAAC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,YAAiB;IAC7C,MAAM,MAAM,GAAG,YAAY,YAAY,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC;IACxF,OAAO,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU;IACrC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE;QAC1C,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE;YAC5B,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;SAC3B;KACJ;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,MAAM,OAAgB,MAAM;IAUxB,SAAS,CAAuB,GAAW,EAAE,IAAuB,EAAE,YAAyB;QAC3F,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAoB,CAAC;QAC5D,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,GAAG,CAAuB,GAAW,EAAE,IAAuB,EAAE,YAAyB;QACrF,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QACpD,IAAI,GAAG,IAAI,IAAI,EAAE;YACb,MAAM,IAAI,WAAW,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAAC;SAC5D;QACD,OAAO,GAAG,CAAC;IACf,CAAC;IAED,MAAM,CAAC,GAAW;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACrC,CAAC;IAED,SAAS,CAAC,GAAW,EAAE,YAAqB;QACxC,OAAO,IAAI,CAAC,GAAG,CAAS,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IACvD,CAAC;IAED,SAAS,CAAC,GAAW,EAAE,YAA8B;QACjD,OAAO,IAAI,CAAC,GAAG,CAAS,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IACvD,CAAC;IAED,UAAU,CAAC,GAAW,EAAE,YAA+B;QACnD,OAAO,IAAI,CAAC,GAAG,CAAU,GAAG,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IACzD,CAAC;;AAlCM,cAAO,GAAgD;IAC1D,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;CACxB,CAAC;AAkCN,MAAM,OAAO,SAAU,SAAQ,MAAM;IAGjC,YAAY,UAAkE,EAAE;QAC5E,KAAK,EAAE,CAAC;QAHZ,QAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;QAI5B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,EAAE;YAC1B,IAAI,CAAC,IAAI,IAAI,EAAE;gBACX,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;aACtB;SACJ;IACL,CAAC;IAED,OAAO,CAAC,GAAW;QACf,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACrC,CAAC;CACJ;AAED,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAC3C;QACI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;CACJ;AAED,SAAS,WAAW,CAAC,GAAW;IAC5B,OAAO,GAAG,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACxB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AACnC,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC7B,OAAO,GAAG,KAAK,MAAM,CAAC;AAC1B,CAAC;AAED,MAAM,OAAO,WAAY,SAAQ,KAAK;IAAtC;;QACa,SAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IAC1C,CAAC;CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './config.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/main/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mesh-config",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Configuration microframework for Mesh IoC",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./out/main/index.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "out/main/index.js",
|
|
11
|
+
"types": "out/main/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"out/main/**/*"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"clean": "rm -rf out *.tsbuildinfo",
|
|
17
|
+
"dev": "npm run clean && tsc -b -w",
|
|
18
|
+
"compile": "npm run clean && tsc -b",
|
|
19
|
+
"lint": "eslint --ext=.js,.ts,.vue --cache .",
|
|
20
|
+
"test": "NODE_ENV=test mocha",
|
|
21
|
+
"preversion": "npm run lint",
|
|
22
|
+
"version": "npm run compile",
|
|
23
|
+
"postversion": "npm publish --access=public && git push origin main --tags"
|
|
24
|
+
},
|
|
25
|
+
"pre-commit": [
|
|
26
|
+
"lint"
|
|
27
|
+
],
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+ssh://git@github.com/MeshIoc/mesh-config.git"
|
|
31
|
+
},
|
|
32
|
+
"author": "Boris Okunskiy",
|
|
33
|
+
"license": "ISC",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"mesh-ioc": "^3.2.0",
|
|
36
|
+
"reflect-utils": "^1.0.3"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@nodescript/eslint-config": "^1.0.0",
|
|
40
|
+
"@types/mocha": "^8.2.3",
|
|
41
|
+
"@types/node": "^16.3.1",
|
|
42
|
+
"chalk": "^4.1.2",
|
|
43
|
+
"eslint": "^8.24.0",
|
|
44
|
+
"mocha": "^9.0.2",
|
|
45
|
+
"pre-commit": "^1.2.2",
|
|
46
|
+
"reflect-metadata": "^0.1.13",
|
|
47
|
+
"typescript": "^4.3.5"
|
|
48
|
+
}
|
|
49
|
+
}
|