@hg-ts/config-loader 0.1.53 → 0.1.55
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/package.json +10 -10
- package/.eslintcache +0 -1
- package/.turbo/turbo-build.log +0 -2
- package/.turbo/turbo-lint$colon$ts.log +0 -2
- package/.turbo/turbo-test.log +0 -26
- package/src/config-loader.ts +0 -112
- package/src/exceptions/index.ts +0 -1
- package/src/exceptions/no-base-config.exception.ts +0 -7
- package/src/index.ts +0 -4
- package/src/path-builder.ts +0 -158
- package/src/tests/config-loader.test.ts +0 -83
- package/src/tests/path-builder.test.ts +0 -133
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hg-ts/config-loader",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.55",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js"
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
"test:dev": "yarn build:dev --onSuccess \"yarn test\""
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@hg-ts-config/typescript": "0.1.
|
|
20
|
-
"@hg-ts/exception": "0.1.
|
|
21
|
-
"@hg-ts/execution-mode": "0.1.
|
|
22
|
-
"@hg-ts/linter": "0.1.
|
|
23
|
-
"@hg-ts/tests": "0.1.
|
|
24
|
-
"@hg-ts/types": "0.1.
|
|
19
|
+
"@hg-ts-config/typescript": "0.1.55",
|
|
20
|
+
"@hg-ts/exception": "0.1.55",
|
|
21
|
+
"@hg-ts/execution-mode": "0.1.55",
|
|
22
|
+
"@hg-ts/linter": "0.1.55",
|
|
23
|
+
"@hg-ts/tests": "0.1.55",
|
|
24
|
+
"@hg-ts/types": "0.1.55",
|
|
25
25
|
"@types/node": "22.10.6",
|
|
26
26
|
"eslint": "9.18.0",
|
|
27
27
|
"reflect-metadata": "0.2.2",
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"typescript": "5.7.3"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@hg-ts/exception": "0.1.
|
|
34
|
-
"@hg-ts/execution-mode": "0.1.
|
|
33
|
+
"@hg-ts/exception": "0.1.55",
|
|
34
|
+
"@hg-ts/execution-mode": "0.1.55",
|
|
35
35
|
"reflect-metadata": "*",
|
|
36
36
|
"tslib": "*"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@hg-ts/validation": "0.1.
|
|
39
|
+
"@hg-ts/validation": "0.1.55"
|
|
40
40
|
}
|
|
41
41
|
}
|
package/.eslintcache
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[{"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/config-loader.js":"1","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/exceptions/index.js":"2","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/exceptions/no-base-config.exception.js":"3","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/index.js":"4","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/path-builder.js":"5","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/tests/config-loader.test-suite.js":"6","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/tests/path-builder.test-suite.js":"7","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/eslint.config.mjs":"8","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/config-loader.ts":"9","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/exceptions/index.ts":"10","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/exceptions/no-base-config.exception.ts":"11","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/index.ts":"12","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/path-builder.ts":"13","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/tests/config-loader.test.js":"14","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/tests/path-builder.test.js":"15","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/tests/config-loader.test.ts":"16","/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/tests/path-builder.test.ts":"17"},{"size":2546,"mtime":1746294710076,"results":"18","hashOfConfig":"19"},{"size":214,"mtime":1746294710067,"results":"20","hashOfConfig":"19"},{"size":439,"mtime":1746294710066,"results":"21","hashOfConfig":"19"},{"size":257,"mtime":1746294710078,"results":"22","hashOfConfig":"19"},{"size":2516,"mtime":1746294710072,"results":"23","hashOfConfig":"19"},{"size":3441,"mtime":1746294464036,"results":"24","hashOfConfig":"19"},{"size":7594,"mtime":1746294464037,"results":"25","hashOfConfig":"19"},{"size":59,"mtime":1736896000121,"results":"26","hashOfConfig":"19"},{"size":2910,"mtime":1740598669135,"results":"27","hashOfConfig":"28"},{"size":44,"mtime":1736876770669,"results":"29","hashOfConfig":"28"},{"size":215,"mtime":1736876770669,"results":"30","hashOfConfig":"28"},{"size":84,"mtime":1736876770669,"results":"31","hashOfConfig":"28"},{"size":3437,"mtime":1736876770669,"results":"32","hashOfConfig":"28"},{"size":3380,"mtime":1746294710082,"results":"33","hashOfConfig":"19"},{"size":7498,"mtime":1746294710088,"results":"34","hashOfConfig":"19"},{"size":1616,"mtime":1740598032887,"results":"35","hashOfConfig":"28"},{"size":4013,"mtime":1740598032885,"results":"36","hashOfConfig":"28"},{"filePath":"37","messages":"38","suppressedMessages":"39","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1gtnk1i",{"filePath":"40","messages":"41","suppressedMessages":"42","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"43","messages":"44","suppressedMessages":"45","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"46","messages":"47","suppressedMessages":"48","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"49","messages":"50","suppressedMessages":"51","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"52","messages":"53","suppressedMessages":"54","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"55","messages":"56","suppressedMessages":"57","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"58","messages":"59","suppressedMessages":"60","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"61","messages":"62","suppressedMessages":"63","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"i5df87",{"filePath":"64","messages":"65","suppressedMessages":"66","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"67","messages":"68","suppressedMessages":"69","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"70","messages":"71","suppressedMessages":"72","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"73","messages":"74","suppressedMessages":"75","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"76","messages":"77","suppressedMessages":"78","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"79","messages":"80","suppressedMessages":"81","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"82","messages":"83","suppressedMessages":"84","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"85","messages":"86","suppressedMessages":"87","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/config-loader.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/exceptions/index.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/exceptions/no-base-config.exception.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/index.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/path-builder.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/tests/config-loader.test-suite.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/tests/path-builder.test-suite.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/eslint.config.mjs",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/config-loader.ts",[],["88"],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/exceptions/index.ts",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/exceptions/no-base-config.exception.ts",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/index.ts",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/path-builder.ts",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/tests/config-loader.test.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/dist/tests/path-builder.test.js",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/tests/config-loader.test.ts",[],[],"/Users/atsapko/WebstormProjects/personnal/framework/packages/config-loader/src/tests/path-builder.test.ts",[],[],{"ruleId":"89","severity":2,"message":"90","line":109,"column":14,"nodeType":"91","messageId":"92","endLine":109,"endColumn":30,"suggestions":"93","suppressions":"94"},"@typescript/class-literal-property-style","Literals should be exposed using readonly fields.","Identifier","preferFieldStyle",["95"],["96"],{"messageId":"97","fix":"98","desc":"99"},{"kind":"100","justification":"101"},"preferFieldStyleSuggestion",{"range":"102","text":"103"},"Replace the literals with readonly fields.","directive","",[2847,2907],"private readonly recursiveRootKey = 'root';"]
|
package/.turbo/turbo-build.log
DELETED
package/.turbo/turbo-test.log
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
▶ ConfigLoaderTest
|
|
3
|
-
[32m✔ simple [90m(0.800459ms)[39m[39m
|
|
4
|
-
[32m✔ recursive [90m(0.208833ms)[39m[39m
|
|
5
|
-
[32m✔ enforceEnv [90m(1.756167ms)[39m[39m
|
|
6
|
-
[32m✔ ConfigLoaderTest [90m(3.383583ms)[39m[39m
|
|
7
|
-
▶ PathBuilderTest
|
|
8
|
-
[32m✔ simple [90m(0.9625ms)[39m[39m
|
|
9
|
-
[32m✔ recursive [90m(0.204583ms)[39m[39m
|
|
10
|
-
[32m✔ full [90m(0.778375ms)[39m[39m
|
|
11
|
-
[32m✔ configDir [90m(0.23675ms)[39m[39m
|
|
12
|
-
[32m✔ envBuilder [90m(0.157542ms)[39m[39m
|
|
13
|
-
[32m✔ envBuilderWithOverrideProd [90m(0.1745ms)[39m[39m
|
|
14
|
-
[32m✔ envBuilderWithOverrideDev [90m(0.197583ms)[39m[39m
|
|
15
|
-
[32m✔ basePostfix [90m(0.399541ms)[39m[39m
|
|
16
|
-
[32m✔ basePostfixWithOverridePostfix [90m(0.288875ms)[39m[39m
|
|
17
|
-
[32m✔ overridePostfix [90m(0.285083ms)[39m[39m
|
|
18
|
-
[32m✔ PathBuilderTest [90m(4.397291ms)[39m[39m
|
|
19
|
-
[34mℹ tests 13[39m
|
|
20
|
-
[34mℹ suites 2[39m
|
|
21
|
-
[34mℹ pass 13[39m
|
|
22
|
-
[34mℹ fail 0[39m
|
|
23
|
-
[34mℹ cancelled 0[39m
|
|
24
|
-
[34mℹ skipped 0[39m
|
|
25
|
-
[34mℹ todo 0[39m
|
|
26
|
-
[34mℹ duration_ms 167.341417[39m
|
package/src/config-loader.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
|
|
4
|
-
import zod, { ZodSchema, ZodTypeDef } from '@hg-ts/validation';
|
|
5
|
-
|
|
6
|
-
import { NoBaseConfigException } from './exceptions';
|
|
7
|
-
import { PathBuilder, PathBuilderOptions } from './path-builder';
|
|
8
|
-
|
|
9
|
-
export type ConfigLoaderOptions = PathBuilderOptions & {
|
|
10
|
-
recursive?: boolean;
|
|
11
|
-
cache?: boolean;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
type CacheItem = {
|
|
15
|
-
schema: zod.Schema<object>;
|
|
16
|
-
config: object;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export class ConfigLoader {
|
|
20
|
-
private readonly pathBuilder: PathBuilder;
|
|
21
|
-
private readonly options: ConfigLoaderOptions;
|
|
22
|
-
private readonly cacheMap = new Map<string, CacheItem>();
|
|
23
|
-
|
|
24
|
-
public constructor(options: ConfigLoaderOptions = {}) {
|
|
25
|
-
this.pathBuilder = new PathBuilder(options);
|
|
26
|
-
this.options = this.pathBuilder.options;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public async load<ConfigType extends object>(schema: zod.Schema<ConfigType>, name: string): Promise<ConfigType> {
|
|
30
|
-
if (this.cacheMap.has(name)) {
|
|
31
|
-
const cacheItem = this.cacheMap.get(name)!;
|
|
32
|
-
|
|
33
|
-
assert.ok(cacheItem.schema === schema, `cached instance of config "${name}" has another schema`);
|
|
34
|
-
|
|
35
|
-
return cacheItem.config as ConfigType;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const rawConfig = await this.loadRawConfig(name);
|
|
39
|
-
|
|
40
|
-
const config = await this.validate(schema, rawConfig);
|
|
41
|
-
|
|
42
|
-
if (this.cacheEnabled) {
|
|
43
|
-
this.cacheMap.set(name, { schema, config });
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return config;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
private async loadRawConfig(name: string): Promise<unknown> {
|
|
50
|
-
const paths = this.pathBuilder.build(name);
|
|
51
|
-
|
|
52
|
-
const configs = await Promise.all(paths.map(async path => this.loadConfigFile(path)));
|
|
53
|
-
|
|
54
|
-
if (!configs[0]) {
|
|
55
|
-
throw new NoBaseConfigException(name);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return this.mergeConfigs(configs);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
*
|
|
63
|
-
* @todo Add options to add custom loaders with own ext names (for example yaml)
|
|
64
|
-
* @param {string} path
|
|
65
|
-
* @private
|
|
66
|
-
*/
|
|
67
|
-
private async loadConfigFile(path: string): Promise<unknown> {
|
|
68
|
-
try {
|
|
69
|
-
const content = await fs.readFile(path, { encoding: 'utf-8' });
|
|
70
|
-
|
|
71
|
-
return JSON.parse(content) as unknown;
|
|
72
|
-
} catch (error: unknown) {
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
private mergeConfigs(configs: unknown[]): Record<string, unknown> {
|
|
78
|
-
return configs
|
|
79
|
-
.filter(config => config !== null)
|
|
80
|
-
.filter((config): config is Record<string, unknown> => typeof config === 'object')
|
|
81
|
-
.reduce((merged, next) => {
|
|
82
|
-
if (this.isRecursive && merged[this.recursiveRootKey] === true) {
|
|
83
|
-
return merged;
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
...merged,
|
|
87
|
-
...next,
|
|
88
|
-
};
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private async validate<ConfigType>(
|
|
93
|
-
schema: ZodSchema<ConfigType, ZodTypeDef, unknown>,
|
|
94
|
-
config: unknown,
|
|
95
|
-
): Promise<ConfigType> {
|
|
96
|
-
return schema.parseAsync(config);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private get cacheEnabled(): boolean {
|
|
100
|
-
return this.options.cache ?? false;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private get isRecursive(): boolean {
|
|
104
|
-
return this.options.recursive ?? false;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// TODO: Get field name from options
|
|
108
|
-
// eslint-disable-next-line @typescript/class-literal-property-style
|
|
109
|
-
private get recursiveRootKey(): string {
|
|
110
|
-
return 'root';
|
|
111
|
-
}
|
|
112
|
-
}
|
package/src/exceptions/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './no-base-config.exception';
|
package/src/index.ts
DELETED
package/src/path-builder.ts
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import type { ExecutionMode } from '@hg-ts/execution-mode';
|
|
2
|
-
import {
|
|
3
|
-
dirname,
|
|
4
|
-
resolve,
|
|
5
|
-
} from 'path';
|
|
6
|
-
|
|
7
|
-
export type PathBuilderOptions = {
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* Override default app path
|
|
12
|
-
* @default process.cwd()
|
|
13
|
-
*/
|
|
14
|
-
appPath?: string;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* Additional directory to appPath
|
|
19
|
-
* @default null
|
|
20
|
-
*/
|
|
21
|
-
configDir?: Nullable<string>;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
* Use environment variable for build config.
|
|
26
|
-
* Get base config, apply ${env} config and, after, apply local config
|
|
27
|
-
* @default false
|
|
28
|
-
*/
|
|
29
|
-
envBuilder?: boolean;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
33
|
-
* Override injected env
|
|
34
|
-
* Uses only with envBuilder: true
|
|
35
|
-
*/
|
|
36
|
-
overrideEnv?: Nullable<ExecutionMode>;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
40
|
-
* Used for loading root package config. Useful with overridePostfix option
|
|
41
|
-
* @default null
|
|
42
|
-
* @todo Implement
|
|
43
|
-
*/
|
|
44
|
-
basePostfix?: Nullable<string>;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
48
|
-
* Useful with basePostfix.
|
|
49
|
-
* For example:
|
|
50
|
-
* You can specify configName to 'hg', basePostfix to 'config' and overridePostfix to 'override'.
|
|
51
|
-
* In this case will be loaded 'bg.config.{ext}' and overrode by 'hg.override.{ext}'.
|
|
52
|
-
* Similar scheme used by many tools like 'docker-compose'.
|
|
53
|
-
* @default null
|
|
54
|
-
* @todo Implement
|
|
55
|
-
*/
|
|
56
|
-
overridePostfix?: Nullable<string>;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Apply all configs from `appDir` to `/` until `root` field won't be specified
|
|
60
|
-
* @default false
|
|
61
|
-
* @todo Implement
|
|
62
|
-
*/
|
|
63
|
-
recursive?: boolean;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export class PathBuilder {
|
|
67
|
-
public readonly options: Required<PathBuilderOptions>;
|
|
68
|
-
private paths: string[];
|
|
69
|
-
|
|
70
|
-
public constructor(options: PathBuilderOptions = {}) {
|
|
71
|
-
this.options = {
|
|
72
|
-
appPath: process.cwd(),
|
|
73
|
-
configDir: null,
|
|
74
|
-
envBuilder: false,
|
|
75
|
-
overrideEnv: null,
|
|
76
|
-
overridePostfix: null,
|
|
77
|
-
basePostfix: null,
|
|
78
|
-
recursive: false,
|
|
79
|
-
...options,
|
|
80
|
-
};
|
|
81
|
-
this.paths = [];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public build(name: string): string[] {
|
|
85
|
-
return this.prepareBasePaths()
|
|
86
|
-
.addEnvFolders()
|
|
87
|
-
.addConfigName(name)
|
|
88
|
-
.paths;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
protected prepareBasePaths(): this {
|
|
92
|
-
const { appPath, configDir, recursive } = this.options;
|
|
93
|
-
if (recursive) {
|
|
94
|
-
let nextPath = appPath;
|
|
95
|
-
const basePaths: string[] = [appPath];
|
|
96
|
-
|
|
97
|
-
while (nextPath !== '/') {
|
|
98
|
-
nextPath = dirname(nextPath);
|
|
99
|
-
basePaths.push(nextPath);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
this.paths = basePaths;
|
|
103
|
-
|
|
104
|
-
if (configDir) {
|
|
105
|
-
this.mergePaths([configDir]);
|
|
106
|
-
}
|
|
107
|
-
} else {
|
|
108
|
-
this.paths = [this.buildPathToConfig([appPath, configDir])];
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return this;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
protected addEnvFolders(): this {
|
|
115
|
-
const { envBuilder, overrideEnv } = this.options;
|
|
116
|
-
const envFolders: string[] = [];
|
|
117
|
-
|
|
118
|
-
if (!envBuilder) {
|
|
119
|
-
return this;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
envFolders.push('base');
|
|
123
|
-
|
|
124
|
-
if (overrideEnv) {
|
|
125
|
-
envFolders.push(overrideEnv.getValue());
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
envFolders.push('local');
|
|
129
|
-
|
|
130
|
-
return this.mergePaths(envFolders);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
protected addConfigName(configName: string): this {
|
|
134
|
-
const { overridePostfix, basePostfix } = this.options;
|
|
135
|
-
const baseName = basePostfix ? `${configName}.${basePostfix}.json` : `${configName}.json`;
|
|
136
|
-
const overrideName = overridePostfix ? `${configName}.${overridePostfix}.json` : null;
|
|
137
|
-
|
|
138
|
-
const names = [baseName];
|
|
139
|
-
|
|
140
|
-
if (overrideName) {
|
|
141
|
-
names.push(overrideName);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return this.mergePaths(names);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
private mergePaths(additionalParts: string[]): this {
|
|
148
|
-
this.paths = this.paths.flatMap(path => additionalParts.map(part => this.buildPathToConfig([path, part])));
|
|
149
|
-
|
|
150
|
-
return this;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
private buildPathToConfig(parts: Nullable<string>[]): string {
|
|
154
|
-
const filteredParts = parts.filter((part): part is string => part !== null);
|
|
155
|
-
|
|
156
|
-
return resolve(...filteredParts);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import zod from '@hg-ts/validation';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
Describe,
|
|
5
|
-
expect,
|
|
6
|
-
Test,
|
|
7
|
-
Suite,
|
|
8
|
-
} from '@hg-ts/tests';
|
|
9
|
-
|
|
10
|
-
import { ConfigLoader } from '../config-loader';
|
|
11
|
-
|
|
12
|
-
@Describe()
|
|
13
|
-
export class ConfigLoaderTest extends Suite {
|
|
14
|
-
@Test()
|
|
15
|
-
public async simple(): Promise<void> {
|
|
16
|
-
const loader = new ConfigLoader();
|
|
17
|
-
|
|
18
|
-
const merged = loader['mergeConfigs']([
|
|
19
|
-
{
|
|
20
|
-
a: 'a',
|
|
21
|
-
b: 'b',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
a: 'aa',
|
|
25
|
-
c: 'c',
|
|
26
|
-
},
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
expect(merged['a']).toBe('aa');
|
|
30
|
-
expect(merged['b']).toBe('b');
|
|
31
|
-
expect(merged['c']).toBe('c');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@Test()
|
|
35
|
-
public async recursive(): Promise<void> {
|
|
36
|
-
const loader = new ConfigLoader({ recursive: true });
|
|
37
|
-
|
|
38
|
-
const merged = loader['mergeConfigs']([
|
|
39
|
-
{
|
|
40
|
-
a: 'a',
|
|
41
|
-
b: 'b',
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
a: 'aa',
|
|
45
|
-
c: 'c',
|
|
46
|
-
root: true,
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
a: 'aaa',
|
|
50
|
-
b: 'bbb',
|
|
51
|
-
c: 'ccc',
|
|
52
|
-
},
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
expect(merged['a']).toBe('aa');
|
|
56
|
-
expect(merged['b']).toBe('b');
|
|
57
|
-
expect(merged['c']).toBe('c');
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
@Test()
|
|
61
|
-
public async enforceEnv(): Promise<void> {
|
|
62
|
-
const loader = new ConfigLoader();
|
|
63
|
-
const configSchema = zod.object({
|
|
64
|
-
number: zod.union([zod.number(), zod.string()])
|
|
65
|
-
.enforceEnv('SOME_NUMERIC_ENV')
|
|
66
|
-
.transform(value => Number(value))
|
|
67
|
-
.pipe(zod.number()),
|
|
68
|
-
bool: zod.union([zod.string(), zod.boolean()])
|
|
69
|
-
.enforceEnv('SOME_BOOLEAN_ENV')
|
|
70
|
-
.transformBooleanString(),
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
process.env['SOME_NUMERIC_ENV'] = '10';
|
|
74
|
-
process.env['SOME_BOOLEAN_ENV'] = 'false';
|
|
75
|
-
|
|
76
|
-
const config = { number: 1, bool: true };
|
|
77
|
-
|
|
78
|
-
const transformed = await loader['validate'](configSchema, config);
|
|
79
|
-
|
|
80
|
-
expect(transformed.number).toBe(10);
|
|
81
|
-
expect(transformed.bool).toBe(false);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Describe,
|
|
3
|
-
expect,
|
|
4
|
-
Test,
|
|
5
|
-
Suite,
|
|
6
|
-
} from '@hg-ts/tests';
|
|
7
|
-
import {
|
|
8
|
-
ExecutionModeVariants,
|
|
9
|
-
MockExecutionMode,
|
|
10
|
-
} from '@hg-ts/execution-mode';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
PathBuilder,
|
|
14
|
-
PathBuilderOptions,
|
|
15
|
-
} from '../path-builder';
|
|
16
|
-
|
|
17
|
-
@Describe()
|
|
18
|
-
export class PathBuilderTest extends Suite {
|
|
19
|
-
@Test()
|
|
20
|
-
public async simple(): Promise<void> {
|
|
21
|
-
const paths = this.getPaths();
|
|
22
|
-
|
|
23
|
-
expect(paths).toHaveLength(1);
|
|
24
|
-
expect(paths[0]).toBe('/tmp/example.json');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@Test()
|
|
28
|
-
public async recursive(): Promise<void> {
|
|
29
|
-
const paths = this.getPaths({ recursive: true });
|
|
30
|
-
|
|
31
|
-
expect(paths).toHaveLength(2);
|
|
32
|
-
expect(paths[0]).toBe('/tmp/example.json');
|
|
33
|
-
expect(paths[1]).toBe('/example.json');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
@Test()
|
|
37
|
-
public async full(): Promise<void> {
|
|
38
|
-
const paths = this.getPaths({
|
|
39
|
-
recursive: true,
|
|
40
|
-
overridePostfix: 'override',
|
|
41
|
-
basePostfix: 'config',
|
|
42
|
-
envBuilder: true,
|
|
43
|
-
overrideEnv: new MockExecutionMode(ExecutionModeVariants.DEMO),
|
|
44
|
-
configDir: 'config',
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
let index = 0;
|
|
48
|
-
|
|
49
|
-
expect(paths).toHaveLength(12);
|
|
50
|
-
expect(paths[index++]).toBe('/tmp/config/base/example.config.json');
|
|
51
|
-
expect(paths[index++]).toBe('/tmp/config/base/example.override.json');
|
|
52
|
-
expect(paths[index++]).toBe('/tmp/config/demo/example.config.json');
|
|
53
|
-
expect(paths[index++]).toBe('/tmp/config/demo/example.override.json');
|
|
54
|
-
expect(paths[index++]).toBe('/tmp/config/local/example.config.json');
|
|
55
|
-
expect(paths[index++]).toBe('/tmp/config/local/example.override.json');
|
|
56
|
-
|
|
57
|
-
expect(paths[index++]).toBe('/config/base/example.config.json');
|
|
58
|
-
expect(paths[index++]).toBe('/config/base/example.override.json');
|
|
59
|
-
expect(paths[index++]).toBe('/config/demo/example.config.json');
|
|
60
|
-
expect(paths[index++]).toBe('/config/demo/example.override.json');
|
|
61
|
-
expect(paths[index++]).toBe('/config/local/example.config.json');
|
|
62
|
-
expect(paths[index++]).toBe('/config/local/example.override.json');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
@Test()
|
|
66
|
-
public async configDir(): Promise<void> {
|
|
67
|
-
const paths = this.getPaths({ configDir: 'config' });
|
|
68
|
-
|
|
69
|
-
expect(paths).toHaveLength(1);
|
|
70
|
-
expect(paths[0]).toBe('/tmp/config/example.json');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
@Test()
|
|
74
|
-
public async envBuilder(): Promise<void> {
|
|
75
|
-
const paths = this.getPaths({ envBuilder: true });
|
|
76
|
-
|
|
77
|
-
expect(paths).toHaveLength(2);
|
|
78
|
-
expect(paths[0]).toBe('/tmp/base/example.json');
|
|
79
|
-
expect(paths[1]).toBe('/tmp/local/example.json');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@Test()
|
|
83
|
-
public async envBuilderWithOverrideProd(): Promise<void> {
|
|
84
|
-
const paths = this.getPaths({ envBuilder: true, overrideEnv: new MockExecutionMode(ExecutionModeVariants.PROD) });
|
|
85
|
-
|
|
86
|
-
expect(paths).toHaveLength(3);
|
|
87
|
-
expect(paths[0]).toBe('/tmp/base/example.json');
|
|
88
|
-
expect(paths[1]).toBe('/tmp/prod/example.json');
|
|
89
|
-
expect(paths[2]).toBe('/tmp/local/example.json');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
@Test()
|
|
93
|
-
public async envBuilderWithOverrideDev(): Promise<void> {
|
|
94
|
-
const paths = this.getPaths({ envBuilder: true, overrideEnv: new MockExecutionMode(ExecutionModeVariants.DEV) });
|
|
95
|
-
|
|
96
|
-
expect(paths).toHaveLength(3);
|
|
97
|
-
expect(paths[0]).toBe('/tmp/base/example.json');
|
|
98
|
-
expect(paths[1]).toBe('/tmp/dev/example.json');
|
|
99
|
-
expect(paths[2]).toBe('/tmp/local/example.json');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
@Test()
|
|
103
|
-
public async basePostfix(): Promise<void> {
|
|
104
|
-
const paths = this.getPaths({ basePostfix: 'config' });
|
|
105
|
-
|
|
106
|
-
expect(paths).toHaveLength(1);
|
|
107
|
-
expect(paths[0]).toBe('/tmp/example.config.json');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
@Test()
|
|
111
|
-
public async basePostfixWithOverridePostfix(): Promise<void> {
|
|
112
|
-
const paths = this.getPaths({ basePostfix: 'config', overridePostfix: 'override' });
|
|
113
|
-
|
|
114
|
-
expect(paths).toHaveLength(2);
|
|
115
|
-
expect(paths[0]).toBe('/tmp/example.config.json');
|
|
116
|
-
expect(paths[1]).toBe('/tmp/example.override.json');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
@Test()
|
|
120
|
-
public async overridePostfix(): Promise<void> {
|
|
121
|
-
const paths = this.getPaths({ overridePostfix: 'override' });
|
|
122
|
-
|
|
123
|
-
expect(paths).toHaveLength(2);
|
|
124
|
-
expect(paths[0]).toBe('/tmp/example.json');
|
|
125
|
-
expect(paths[1]).toBe('/tmp/example.override.json');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private getPaths(options: Omit<PathBuilderOptions, 'appPath'> = {}): string[] {
|
|
129
|
-
const builder = new PathBuilder({ appPath: '/tmp', ...options });
|
|
130
|
-
|
|
131
|
-
return builder.build('example');
|
|
132
|
-
}
|
|
133
|
-
}
|