1
- const _ = require ( 'lodash' ) ;
2
- const { buildLazyObject, forceParsing} = require ( './lazy' ) ;
3
- const { MissingOptionError, UnknownKeysError} = require ( './errors' ) ;
4
- const initLocator = require ( './locator' ) ;
1
+ import _ from 'lodash' ;
2
+
3
+ import { MissingOptionError , UnknownKeysError } from './errors' ;
4
+ import { buildLazyObject , forceParsing } from './lazy' ;
5
+ import initLocator from './locator' ;
6
+
7
+ import type { LazyObject } from './types/lazy' ;
8
+ import type { RootParsedConfig } from './types/common' ;
9
+ import type { MapParser } from './types/map' ;
10
+ import type { OptionParser , OptionParserConfig } from './types/option' ;
11
+ import type { RootParser , RootPrefixes , ConfigParser } from './types/root' ;
12
+ import type { SectionParser , SectionProperties } from './types/section' ;
13
+ import type { DeepPartial } from './types/utils' ;
14
+ import type { Locator } from './types/locator' ;
15
+
16
+ type Parser < T , R = any > = OptionParser < T , R > | SectionParser < T , R > | MapParser < T , R > ;
5
17
6
18
/**
7
19
* Single option
8
20
*/
9
- function option ( {
21
+ export function option < T , S = T , R = any > ( {
10
22
defaultValue,
11
23
parseCli = _ . identity ,
12
24
parseEnv = _ . identity ,
13
25
validate = _ . noop ,
14
26
map : mapFunc = _ . identity
15
- } ) {
27
+ } : OptionParserConfig < T , S , R > ) : OptionParser < S , R > {
28
+ const validateFunc : typeof validate = validate ;
29
+
16
30
return ( locator , parsed ) => {
17
31
const config = parsed . root ;
18
- const currNode = locator . parent ? _ . get ( config , locator . parent ) : config ;
32
+ const currNode = locator . parent ? _ . get ( parsed , locator . parent ) : config ;
19
33
20
- let value ;
34
+ let value : unknown ;
21
35
if ( locator . cliOption !== undefined ) {
22
36
value = parseCli ( locator . cliOption ) ;
23
37
} else if ( locator . envVar !== undefined ) {
@@ -31,7 +45,8 @@ function option({
31
45
} else {
32
46
throw new MissingOptionError ( locator . name ) ;
33
47
}
34
- validate ( value , config , currNode ) ;
48
+
49
+ validateFunc ( value , config , currNode ) ;
35
50
36
51
return mapFunc ( value , config , currNode ) ;
37
52
} ;
@@ -41,13 +56,15 @@ function option({
41
56
* Object with fixed properties.
42
57
* Any unknown property will be reported as error.
43
58
*/
44
- function section ( properties ) {
45
- const expectedKeys = _ . keys ( properties ) ;
59
+ export function section < T , R = any > ( properties : SectionProperties < T , R > ) : SectionParser < T , R > {
60
+ const expectedKeys = _ . keys ( properties ) as Array < keyof T > ;
61
+
46
62
return ( locator , config ) => {
47
63
const unknownKeys = _ . difference (
48
64
_ . keys ( locator . option ) ,
49
- expectedKeys
65
+ expectedKeys as Array < string >
50
66
) ;
67
+
51
68
if ( unknownKeys . length > 0 ) {
52
69
throw new UnknownKeysError (
53
70
unknownKeys . map ( ( key ) => `${ locator . name } .${ key } ` )
@@ -56,7 +73,8 @@ function section(properties) {
56
73
57
74
const lazyResult = buildLazyObject ( expectedKeys , ( key ) => {
58
75
const parser = properties [ key ] ;
59
- return ( ) => parser ( locator . nested ( key ) , config ) ;
76
+
77
+ return ( ) => parser ( locator . nested ( key ) as Locator < DeepPartial < T [ keyof T ] > > , config ) ;
60
78
} ) ;
61
79
62
80
_ . set ( config , locator . name , lazyResult ) ;
@@ -69,32 +87,33 @@ function section(properties) {
69
87
* Object with user-specified keys and values,
70
88
* parsed by valueParser.
71
89
*/
72
- function map ( valueParser , defaultValue ) {
90
+ export function map < T extends Record < string , any > , V extends T [ string ] = T [ string ] , R = any > (
91
+ valueParser : Parser < V , R > ,
92
+ defaultValue : DeepPartial < Record < string , V > >
93
+ ) : MapParser < Record < string , V > , R > {
73
94
return ( locator , config ) => {
74
95
if ( locator . option === undefined ) {
75
96
if ( ! defaultValue ) {
76
- return { } ;
97
+ return { } as LazyObject < T > ;
77
98
}
78
99
locator = locator . resetOption ( defaultValue ) ;
79
100
}
80
101
81
- const optionsToParse = Object . keys ( locator . option ) ;
82
- const lazyResult = buildLazyObject ( optionsToParse , ( key ) => {
83
- return ( ) => valueParser ( locator . nested ( key ) , config ) ;
102
+ const optionsToParse = Object . keys ( locator . option as Record < string , V > ) ;
103
+ const lazyResult = buildLazyObject < Record < string , V > > ( optionsToParse , ( key ) => {
104
+ return ( ) => valueParser ( locator . nested ( key ) as Locator < DeepPartial < T [ keyof T ] > > , config ) ;
84
105
} ) ;
85
106
_ . set ( config , locator . name , lazyResult ) ;
86
107
87
108
return lazyResult ;
88
109
} ;
89
110
}
90
111
91
- function root ( rootParser , { envPrefix, cliPrefix} ) {
112
+ export function root < T > ( rootParser : RootParser < T > , { envPrefix, cliPrefix} : RootPrefixes ) : ConfigParser < T > {
92
113
return ( { options, env, argv} ) => {
93
114
const rootLocator = initLocator ( { options, env, argv, envPrefix, cliPrefix} ) ;
94
- const parsed = { } ;
95
- rootParser ( rootLocator , parsed ) ;
96
- return forceParsing ( parsed . root ) ;
115
+ const parsed = rootParser ( rootLocator , { } as RootParsedConfig < T > ) ;
116
+
117
+ return forceParsing ( parsed ) ;
97
118
} ;
98
119
}
99
-
100
- module . exports = { option, section, map, root} ;
0 commit comments