/
index.d.ts
210 lines (180 loc) · 7.02 KB
/
index.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/// <reference types="node" />
declare namespace convict {
// Taken from https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-307871458
type Overwrite<T, U> = { [P in Exclude<keyof T, keyof U>]: T[P] } & U;
type ValidationMethod = "strict" | "warn";
interface ValidateOptions {
/**
* If set to warn, any properties specified in config files that are not declared in
* the schema will print a warning. This is the default behavior. If set to strict,
* any properties specified in config files that are not declared in the schema will
* throw errors. This is to ensure that the schema and the config files are in sync.
*/
allowed?: ValidationMethod | undefined;
/** @deprecated use allowed instead */
strict?: boolean | undefined;
/**
* If specified, possible warnings will be passed to this function instead of being
* outputted to console.log, which would be the default behaviour.
*/
output?: ((message: string) => void) | undefined;
}
interface Format {
name?: string | undefined;
validate?(val: any, schema: SchemaObj): void;
coerce?(val: any): any;
}
interface Parser {
extension: string | string[];
parse: (content: string) => any;
}
type PredefinedFormat =
| "*"
| "int"
| "port"
| "windows_named_pipe"
| "port_or_windows_named_pipe"
| "url"
| "email"
| "ipaddress"
| "duration"
| "timestamp"
| "nat"
| String
| Object
| Number
| RegExp
| Boolean;
interface SchemaObj<T = any> {
/**
* You can define a configuration property as "required" without providing a default value.
* Set its default to null and if your format doesn't accept null it will throw an error.
*/
default: T | null;
doc?: string | undefined;
/**
* From the implementation:
*
* format can be a:
* - predefined type, as seen below
* - an array of enumerated values, e.g. ["production", "development", "testing"]
* - built-in JavaScript type, i.e. Object, Array, String, Number, Boolean
* - function that performs validation and throws an Error on failure
*
* If omitted, format will be set to the value of Object.prototype.toString.call
* for the default value
*/
format?: PredefinedFormat | any[] | ((val: any) => asserts val is T) | ((val: any) => void) | undefined;
env?: string | undefined;
arg?: string | undefined;
sensitive?: boolean | undefined;
nullable?: boolean | undefined;
[key: string]: any;
}
type Schema<T> = {
[P in keyof T]: Schema<T[P]> | SchemaObj<T[P]>;
};
interface InternalSchema<T> {
_cvtProperties: {
[K in keyof T]: T[K] extends object ? InternalSchema<T[K]> : { default: T[K] };
};
}
interface Options {
env?: NodeJS.ProcessEnv | undefined;
args?: string[] | undefined;
}
// Taken from https://twitter.com/diegohaz/status/1309489079378219009
type PathImpl<T, K extends keyof T> = K extends string
? T[K] extends Record<string, any>
? T[K] extends ArrayLike<any> ? K | `${K}.${PathImpl<T[K], Exclude<keyof T[K], keyof any[]>>}`
: K | `${K}.${PathImpl<T[K], keyof T[K]>}`
: K
: never;
type Path<T> = PathImpl<T, keyof T> | keyof T;
type PathValue<T, P extends Path<T>> = P extends `${infer K}.${infer Rest}`
? K extends keyof T ? Rest extends Path<T[K]> ? PathValue<T[K], Rest>
: never
: never
: P extends keyof T ? T[P]
: never;
interface Config<T> {
/**
* @returns the current value of the name property. name can use dot
* notation to reference nested values
*/
get<K extends Path<T> | null | undefined = undefined>(
name?: K,
): K extends null | undefined ? T : K extends Path<T> ? PathValue<T, K> : never;
/**
* @returns the default value of the name property. name can use dot
* notation to reference nested values
*/
default<K extends Path<T> | null | undefined = undefined>(
name?: K,
): K extends null | undefined ? T : K extends Path<T> ? PathValue<T, K> : never;
/**
* @returns true if the property name is defined, or false otherwise
*/
has<K extends Path<T>>(name: K): boolean;
/**
* Resets a property to its default value as defined in the schema
*/
reset<K extends Path<T>>(name: K): void;
/**
* Sets the value of name to value. name can use dot notation to reference
* nested values, e.g. "database.port". If objects in the chain don't yet
* exist, they will be initialized to empty objects
*/
set<K extends Path<T> | string>(name: K, value: K extends Path<T> ? PathValue<T, K> : any): Config<T>;
/**
* Loads and merges a JavaScript object into config
*/
load<U>(conf: U): Config<Overwrite<T, U>>;
/**
* Loads and merges JSON configuration file(s) into config
*/
loadFile<U>(files: string | string[]): Config<Overwrite<T, U>>;
/**
* Validates config against the schema used to initialize it
*/
validate(options?: ValidateOptions): Config<T>;
/**
* Exports all the properties (that is the keys and their current values) as a {JSON} {Object}
* @returns A {JSON} compliant {Object}
*/
getProperties(): T;
/**
* Exports the schema as a {JSON} {Object}
* @returns A {JSON} compliant {Object}
*/
getSchema(): InternalSchema<T>;
/**
* Exports all the properties (that is the keys and their current values) as a JSON string.
* @returns A string representing this object
*/
toString(): string;
/**
* Exports the schema as a JSON string.
* @returns A string representing the schema of this {Config}
*/
getSchemaString(): string;
/**
* Gets the environment variable map, using the override passed to the
* convict function or process.env if no override was passed.
*/
getEnv(): string[];
/**
* Gets the array of process arguments, using the override passed to the
* convict function or process.argv if no override was passed.
*/
getArgs(): string[];
}
}
interface convict {
addFormat(format: convict.Format): void;
addFormats(formats: { [name: string]: convict.Format }): void;
addParser(parsers: convict.Parser | convict.Parser[]): void;
<T>(config: convict.Schema<T> | string, opts?: convict.Options): convict.Config<T>;
}
declare var convict: convict;
export = convict;