@takaro/config 0.0.1
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 +36 -0
- package/dist/main.d.ts +22 -0
- package/dist/main.js +55 -0
- package/dist/main.js.map +1 -0
- package/package.json +25 -0
- package/src/__tests__/config.unit.test.ts +32 -0
- package/src/main.ts +71 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +8 -0
- package/typedoc.json +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# @takaro/config
|
|
2
|
+
|
|
3
|
+
An opinionated config manager based on [node-convict](https://github.com/mozilla/node-convict)
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { Config, IBaseConfig } from '@takaro/config';
|
|
9
|
+
|
|
10
|
+
interface IExampleConfig extends IBaseConfig {
|
|
11
|
+
test: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// This is a schema from convict
|
|
15
|
+
const exampleSchema = {
|
|
16
|
+
test: {
|
|
17
|
+
doc: 'Test value',
|
|
18
|
+
format: String,
|
|
19
|
+
default: 'test',
|
|
20
|
+
env: 'TAKARO_TEST'
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const config = new Config<IExampleConfig>([exampleSchema]);
|
|
25
|
+
|
|
26
|
+
// ---
|
|
27
|
+
|
|
28
|
+
config.load({ test: 1 });
|
|
29
|
+
// Error! 'test' should be a string
|
|
30
|
+
config.validate();
|
|
31
|
+
|
|
32
|
+
// ---
|
|
33
|
+
|
|
34
|
+
config.load({ test: 'Hello world' });
|
|
35
|
+
config.get('test') // 'Hello world'
|
|
36
|
+
```
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import convict, { Path, PathValue, Schema } from 'convict';
|
|
2
|
+
export declare enum EXECUTION_MODE {
|
|
3
|
+
LOCAL = "local",
|
|
4
|
+
LAMBDA = "lambda"
|
|
5
|
+
}
|
|
6
|
+
export interface IBaseConfig {
|
|
7
|
+
app: {
|
|
8
|
+
name: string;
|
|
9
|
+
};
|
|
10
|
+
mode: 'development' | 'production' | 'test';
|
|
11
|
+
functions: {
|
|
12
|
+
executionMode: EXECUTION_MODE;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare const baseConfigConvict: Schema<IBaseConfig>;
|
|
16
|
+
export declare class Config<T extends IBaseConfig> {
|
|
17
|
+
_config: convict.Config<T>;
|
|
18
|
+
constructor(valuesArray?: Schema<Partial<T>>[]);
|
|
19
|
+
get<K extends Path<T>>(arg: K): K extends null | undefined ? T : K extends Path<T> ? PathValue<T, K> : never;
|
|
20
|
+
load(data: Partial<T>): void;
|
|
21
|
+
validate(): void;
|
|
22
|
+
}
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import convict from 'convict';
|
|
2
|
+
export var EXECUTION_MODE;
|
|
3
|
+
(function (EXECUTION_MODE) {
|
|
4
|
+
EXECUTION_MODE["LOCAL"] = "local";
|
|
5
|
+
EXECUTION_MODE["LAMBDA"] = "lambda";
|
|
6
|
+
})(EXECUTION_MODE || (EXECUTION_MODE = {}));
|
|
7
|
+
export const baseConfigConvict = {
|
|
8
|
+
app: {
|
|
9
|
+
name: {
|
|
10
|
+
doc: 'Name of the running package',
|
|
11
|
+
format: String,
|
|
12
|
+
default: 'UNNAMED_PACKAGE',
|
|
13
|
+
env: 'APP_NAME',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
mode: {
|
|
17
|
+
doc: 'The application mode',
|
|
18
|
+
format: ['development', 'production', 'test'],
|
|
19
|
+
default: 'production',
|
|
20
|
+
env: 'NODE_ENV',
|
|
21
|
+
},
|
|
22
|
+
functions: {
|
|
23
|
+
executionMode: {
|
|
24
|
+
doc: 'The mode to use when executing functions. Setting to "local" is VERY INSECURE! Only do it if you know what you are doing',
|
|
25
|
+
format: Object.values(EXECUTION_MODE),
|
|
26
|
+
default: EXECUTION_MODE.LAMBDA,
|
|
27
|
+
env: 'FUNCTIONS_EXECUTION_MODE',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
export class Config {
|
|
32
|
+
constructor(valuesArray = []) {
|
|
33
|
+
const values = [...valuesArray, baseConfigConvict].reduce((acc, curr) => {
|
|
34
|
+
return { ...acc, ...curr };
|
|
35
|
+
}, {});
|
|
36
|
+
this._config = convict(values);
|
|
37
|
+
}
|
|
38
|
+
// Thanks Diego :)
|
|
39
|
+
// https://twitter.com/diegohaz/status/1309489079378219009
|
|
40
|
+
get(arg) {
|
|
41
|
+
return this._config.get(arg);
|
|
42
|
+
}
|
|
43
|
+
load(data) {
|
|
44
|
+
this._config.load(data);
|
|
45
|
+
}
|
|
46
|
+
validate() {
|
|
47
|
+
this._config.validate({
|
|
48
|
+
allowed: 'strict',
|
|
49
|
+
output: (str) => {
|
|
50
|
+
throw new Error(str);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,OAAoC,MAAM,SAAS,CAAC;AAE3D,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,mCAAiB,CAAA;AACnB,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB;AAYD,MAAM,CAAC,MAAM,iBAAiB,GAAwB;IACpD,GAAG,EAAE;QACH,IAAI,EAAE;YACJ,GAAG,EAAE,6BAA6B;YAClC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,iBAAiB;YAC1B,GAAG,EAAE,UAAU;SAChB;KACF;IACD,IAAI,EAAE;QACJ,GAAG,EAAE,sBAAsB;QAC3B,MAAM,EAAE,CAAC,aAAa,EAAE,YAAY,EAAE,MAAM,CAAC;QAC7C,OAAO,EAAE,YAAY;QACrB,GAAG,EAAE,UAAU;KAChB;IACD,SAAS,EAAE;QACT,aAAa,EAAE;YACb,GAAG,EAAE,0HAA0H;YAC/H,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC;YACrC,OAAO,EAAE,cAAc,CAAC,MAAM;YAC9B,GAAG,EAAE,0BAA0B;SAChC;KACF;CACF,CAAC;AAEF,MAAM,OAAO,MAAM;IAGjB,YAAY,cAAoC,EAAE;QAChD,MAAM,MAAM,GAAG,CAAC,GAAG,WAAW,EAAE,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACtE,OAAO,EAAE,GAAG,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;QAC7B,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,IAAI,CAAC,OAAO,GAAG,OAAO,CAAI,MAAmB,CAAC,CAAC;IACjD,CAAC;IAED,kBAAkB;IAClB,0DAA0D;IAC1D,GAAG,CAAoB,GAAM;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC,IAAgB;QACnB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;YACpB,OAAO,EAAE,QAAQ;YACjB,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE;gBACtB,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@takaro/config",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "An opinionated config handler",
|
|
5
|
+
"main": "dist/main.js",
|
|
6
|
+
"types": "dist/main.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"start:dev": "tsc --watch --preserveWatchOutput -p ./tsconfig.build.json",
|
|
10
|
+
"build": "tsc -p ./tsconfig.build.json",
|
|
11
|
+
"test": "npm run test:unit --if-present && npm run test:integration --if-present",
|
|
12
|
+
"test:unit": "mocha --config ../../.mocharc.js src/**/*.unit.test.ts",
|
|
13
|
+
"test:integration": "echo 'No tests (yet :))'"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [],
|
|
16
|
+
"author": "",
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"convict": "^6.2.3"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@takaro/test": "0.0.1",
|
|
23
|
+
"@types/convict": "^6.1.1"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { expect } from '@takaro/test';
|
|
2
|
+
|
|
3
|
+
import { Config, IBaseConfig } from '../main.js';
|
|
4
|
+
|
|
5
|
+
interface ITestConfig extends IBaseConfig {
|
|
6
|
+
test: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const testConfigSchema = {
|
|
10
|
+
test: {
|
|
11
|
+
doc: 'Test value',
|
|
12
|
+
format: String,
|
|
13
|
+
default: 'test',
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe('config', () => {
|
|
18
|
+
it('Allows loading one config', () => {
|
|
19
|
+
const config = new Config<ITestConfig>();
|
|
20
|
+
expect(config.get('app.name')).to.equal('UNNAMED_PACKAGE');
|
|
21
|
+
});
|
|
22
|
+
it('Throws an error when validating', () => {
|
|
23
|
+
const config = new Config<ITestConfig>([testConfigSchema]);
|
|
24
|
+
// @ts-expect-error Testing something the compiler could catch...
|
|
25
|
+
config.load({ test: 1 });
|
|
26
|
+
expect(() => config.validate()).to.throw('test: must be of type String: value was 1');
|
|
27
|
+
});
|
|
28
|
+
it('Allows loading multiple configs', () => {
|
|
29
|
+
const config = new Config<ITestConfig>([testConfigSchema]);
|
|
30
|
+
expect(config.get('test')).to.equal('test');
|
|
31
|
+
});
|
|
32
|
+
});
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import convict, { Path, PathValue, Schema } from 'convict';
|
|
2
|
+
|
|
3
|
+
export enum EXECUTION_MODE {
|
|
4
|
+
LOCAL = 'local',
|
|
5
|
+
LAMBDA = 'lambda',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface IBaseConfig {
|
|
9
|
+
app: {
|
|
10
|
+
name: string;
|
|
11
|
+
};
|
|
12
|
+
mode: 'development' | 'production' | 'test';
|
|
13
|
+
functions: {
|
|
14
|
+
executionMode: EXECUTION_MODE;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const baseConfigConvict: Schema<IBaseConfig> = {
|
|
19
|
+
app: {
|
|
20
|
+
name: {
|
|
21
|
+
doc: 'Name of the running package',
|
|
22
|
+
format: String,
|
|
23
|
+
default: 'UNNAMED_PACKAGE',
|
|
24
|
+
env: 'APP_NAME',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
mode: {
|
|
28
|
+
doc: 'The application mode',
|
|
29
|
+
format: ['development', 'production', 'test'],
|
|
30
|
+
default: 'production',
|
|
31
|
+
env: 'NODE_ENV',
|
|
32
|
+
},
|
|
33
|
+
functions: {
|
|
34
|
+
executionMode: {
|
|
35
|
+
doc: 'The mode to use when executing functions. Setting to "local" is VERY INSECURE! Only do it if you know what you are doing',
|
|
36
|
+
format: Object.values(EXECUTION_MODE),
|
|
37
|
+
default: EXECUTION_MODE.LAMBDA,
|
|
38
|
+
env: 'FUNCTIONS_EXECUTION_MODE',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export class Config<T extends IBaseConfig> {
|
|
44
|
+
public _config: convict.Config<T>;
|
|
45
|
+
|
|
46
|
+
constructor(valuesArray: Schema<Partial<T>>[] = []) {
|
|
47
|
+
const values = [...valuesArray, baseConfigConvict].reduce((acc, curr) => {
|
|
48
|
+
return { ...acc, ...curr };
|
|
49
|
+
}, {});
|
|
50
|
+
this._config = convict<T>(values as Schema<T>);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Thanks Diego :)
|
|
54
|
+
// https://twitter.com/diegohaz/status/1309489079378219009
|
|
55
|
+
get<K extends Path<T>>(arg: K): K extends null | undefined ? T : K extends Path<T> ? PathValue<T, K> : never {
|
|
56
|
+
return this._config.get(arg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
load(data: Partial<T>) {
|
|
60
|
+
this._config.load(data);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
validate() {
|
|
64
|
+
this._config.validate({
|
|
65
|
+
allowed: 'strict',
|
|
66
|
+
output: (str: string) => {
|
|
67
|
+
throw new Error(str);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
package/tsconfig.json
ADDED
package/typedoc.json
ADDED