@ix-xs/node-comfort 1.2.0 → 2.1.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/CHANGELOG.md +340 -0
- package/README.md +137 -548
- package/index.js +80 -35
- package/package.json +161 -33
- package/src/Arr.js +1050 -418
- package/src/Async.js +817 -0
- package/src/Cache.js +433 -0
- package/src/Checker.js +1202 -539
- package/src/Cli.js +1293 -0
- package/src/Color.js +556 -0
- package/src/Crypto.js +1082 -0
- package/src/Emitter.js +356 -0
- package/src/Env.js +689 -0
- package/src/FS.js +1626 -894
- package/src/Func.js +823 -356
- package/src/Http.js +700 -0
- package/src/Id.js +568 -200
- package/src/Logger.js +963 -378
- package/src/Num.js +965 -360
- package/src/Obj.js +1077 -379
- package/src/SQLite.js +1629 -1005
- package/src/Schema.js +2101 -0
- package/src/Str.js +1209 -432
- package/src/Sys.js +654 -0
- package/src/Time.js +1533 -440
- package/src/Utils.js +342 -325
- package/src/errors.js +335 -0
- package/src/internal/shared.js +415 -0
- package/types/index.d.ts +735 -526
- package/types/src/Arr.d.ts +533 -145
- package/types/src/Arr.d.ts.map +1 -1
- package/types/src/Async.d.ts +372 -0
- package/types/src/Async.d.ts.map +1 -0
- package/types/src/Cache.d.ts +221 -0
- package/types/src/Cache.d.ts.map +1 -0
- package/types/src/Checker.d.ts +651 -232
- package/types/src/Checker.d.ts.map +1 -1
- package/types/src/Cli.d.ts +664 -0
- package/types/src/Cli.d.ts.map +1 -0
- package/types/src/Color.d.ts +300 -0
- package/types/src/Color.d.ts.map +1 -0
- package/types/src/Crypto.d.ts +620 -0
- package/types/src/Crypto.d.ts.map +1 -0
- package/types/src/Emitter.d.ts +189 -0
- package/types/src/Emitter.d.ts.map +1 -0
- package/types/src/Env.d.ts +412 -0
- package/types/src/Env.d.ts.map +1 -0
- package/types/src/FS.d.ts +717 -238
- package/types/src/FS.d.ts.map +1 -1
- package/types/src/Func.d.ts +508 -135
- package/types/src/Func.d.ts.map +1 -1
- package/types/src/Http.d.ts +444 -0
- package/types/src/Http.d.ts.map +1 -0
- package/types/src/Id.d.ts +199 -66
- package/types/src/Id.d.ts.map +1 -1
- package/types/src/Logger.d.ts +414 -46
- package/types/src/Logger.d.ts.map +1 -1
- package/types/src/Num.d.ts +514 -137
- package/types/src/Num.d.ts.map +1 -1
- package/types/src/Obj.d.ts +453 -104
- package/types/src/Obj.d.ts.map +1 -1
- package/types/src/SQLite.d.ts +754 -308
- package/types/src/SQLite.d.ts.map +1 -1
- package/types/src/Schema.d.ts +1189 -0
- package/types/src/Schema.d.ts.map +1 -0
- package/types/src/Str.d.ts +617 -166
- package/types/src/Str.d.ts.map +1 -1
- package/types/src/Sys.d.ts +314 -0
- package/types/src/Sys.d.ts.map +1 -0
- package/types/src/Time.d.ts +759 -204
- package/types/src/Time.d.ts.map +1 -1
- package/types/src/Utils.d.ts +158 -102
- package/types/src/Utils.d.ts.map +1 -1
- package/types/src/errors.d.ts +316 -0
- package/types/src/errors.d.ts.map +1 -0
- package/types/src/internal/shared.d.ts +123 -0
- package/types/src/internal/shared.d.ts.map +1 -0
- package/types/index.d.ts.map +0 -1
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
export = Emitter;
|
|
2
|
+
/**
|
|
3
|
+
* A typed event emitter. In JavaScript, give the variable a JSDoc type such
|
|
4
|
+
* as `import("@ix-xs/node-comfort").Emitter<{ ready: [port: number] }>`.
|
|
5
|
+
*
|
|
6
|
+
* @template {EventMap} [Events=EventMap]
|
|
7
|
+
*/
|
|
8
|
+
declare class Emitter<Events extends EventMap = EventMap> {
|
|
9
|
+
/**
|
|
10
|
+
* Listens to an event.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const off = emitter.on("data", (chunk) => chunks.push(chunk));
|
|
14
|
+
* off(); // stop listening
|
|
15
|
+
*
|
|
16
|
+
* const controller = new AbortController();
|
|
17
|
+
* emitter.on("data", onData, { signal: controller.signal });
|
|
18
|
+
* emitter.on("end", onEnd, { signal: controller.signal });
|
|
19
|
+
* controller.abort(); // removes both
|
|
20
|
+
*
|
|
21
|
+
* @template {keyof Events & string} K
|
|
22
|
+
* @param {K} event
|
|
23
|
+
* @param {(...args: Events[K]) => unknown} listener
|
|
24
|
+
* @param {ListenOptions} [options]
|
|
25
|
+
* @returns {() => void} Removes the listener.
|
|
26
|
+
*/
|
|
27
|
+
on<K extends keyof Events & string>(event: K, listener: (...args: Events[K]) => unknown, options?: ListenOptions): () => void;
|
|
28
|
+
/**
|
|
29
|
+
* Listens to an event once.
|
|
30
|
+
*
|
|
31
|
+
* @template {keyof Events & string} K
|
|
32
|
+
* @param {K} event
|
|
33
|
+
* @param {(...args: Events[K]) => unknown} listener
|
|
34
|
+
* @param {ListenOptions} [options]
|
|
35
|
+
* @returns {() => void} Removes the listener if it hasn't run yet.
|
|
36
|
+
*/
|
|
37
|
+
once<K extends keyof Events & string>(event: K, listener: (...args: Events[K]) => unknown, options?: ListenOptions): () => void;
|
|
38
|
+
/**
|
|
39
|
+
* Listens to every event; the listener gets the event name first. Handy for
|
|
40
|
+
* logging.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* emitter.onAny((event, ...args) => nc.debug(event, args));
|
|
44
|
+
*
|
|
45
|
+
* @param {(event: keyof Events & string, ...args: any[]) => unknown} listener
|
|
46
|
+
* @returns {() => void} Removes the listener.
|
|
47
|
+
*/
|
|
48
|
+
onAny(listener: (event: keyof Events & string, ...args: any[]) => unknown): () => void;
|
|
49
|
+
/**
|
|
50
|
+
* Removes a listener, or all listeners of the event if you don't pass one.
|
|
51
|
+
*
|
|
52
|
+
* @template {keyof Events & string} K
|
|
53
|
+
* @param {K} event
|
|
54
|
+
* @param {(...args: Events[K]) => unknown} [listener] The function given to `on()` or `once()`.
|
|
55
|
+
* @returns {this}
|
|
56
|
+
*/
|
|
57
|
+
off<K extends keyof Events & string>(event: K, listener?: (...args: Events[K]) => unknown): this;
|
|
58
|
+
/**
|
|
59
|
+
* Calls the event's listeners right away, in the order they were added.
|
|
60
|
+
* If one throws, the error propagates, as with Node's `EventEmitter`.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* emitter.emit("message", "hello", "ada");
|
|
64
|
+
*
|
|
65
|
+
* @template {keyof Events & string} K
|
|
66
|
+
* @param {K} event
|
|
67
|
+
* @param {Events[K]} args
|
|
68
|
+
* @returns {boolean} `true` if anyone was listening.
|
|
69
|
+
*/
|
|
70
|
+
emit<K extends keyof Events & string>(event: K, ...args: Events[K]): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Calls the listeners one at a time, waiting for each, and resolves with
|
|
73
|
+
* what they returned. Good for hooks that may be async.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* await hooks.emitAsync("beforeSave", record);
|
|
77
|
+
*
|
|
78
|
+
* @template {keyof Events & string} K
|
|
79
|
+
* @param {K} event
|
|
80
|
+
* @param {Events[K]} args
|
|
81
|
+
* @returns {Promise<unknown[]>}
|
|
82
|
+
*/
|
|
83
|
+
emitAsync<K extends keyof Events & string>(event: K, ...args: Events[K]): Promise<unknown[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Waits for the next time the event fires and resolves with its arguments.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const [code] = await child.waitFor("exit", { timeout: "30s" });
|
|
89
|
+
* const [text] = await chat.waitFor("message", { filter: (text, from) => from === "ada" });
|
|
90
|
+
*
|
|
91
|
+
* @template {keyof Events & string} K
|
|
92
|
+
* @param {K} event
|
|
93
|
+
* @param {WaitForOptions<Events[K]>} [options]
|
|
94
|
+
* @returns {Promise<Events[K]>}
|
|
95
|
+
* @throws {TimeoutError}
|
|
96
|
+
* @throws {AbortError}
|
|
97
|
+
*/
|
|
98
|
+
waitFor<K extends keyof Events & string>(event: K, options?: WaitForOptions<Events[K]>): Promise<Events[K]>;
|
|
99
|
+
/**
|
|
100
|
+
* Loops over an event with `for await`. Events that fire while your loop
|
|
101
|
+
* body runs are queued, and leaving the loop removes the listener.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* for await (const [job] of queue.iterate("job")) {
|
|
105
|
+
* await process(job);
|
|
106
|
+
* }
|
|
107
|
+
*
|
|
108
|
+
* @template {keyof Events & string} K
|
|
109
|
+
* @param {K} event
|
|
110
|
+
* @param {{ signal?: AbortSignal }} [options] Ends the loop when aborted.
|
|
111
|
+
* @returns {AsyncIterableIterator<Events[K]>}
|
|
112
|
+
*/
|
|
113
|
+
iterate<K extends keyof Events & string>(event: K, options?: {
|
|
114
|
+
signal?: AbortSignal;
|
|
115
|
+
}): AsyncIterableIterator<Events[K]>;
|
|
116
|
+
/**
|
|
117
|
+
* How many listeners an event has, or all events together. `onAny`
|
|
118
|
+
* listeners aren't counted.
|
|
119
|
+
*
|
|
120
|
+
* @param {keyof Events & string} [event]
|
|
121
|
+
* @returns {number}
|
|
122
|
+
*/
|
|
123
|
+
listenerCount(event?: keyof Events & string): number;
|
|
124
|
+
/**
|
|
125
|
+
* The listeners of an event, in the order they run. For `once()`, you get
|
|
126
|
+
* the function you passed, not its wrapper.
|
|
127
|
+
*
|
|
128
|
+
* @template {keyof Events & string} K
|
|
129
|
+
* @param {K} event
|
|
130
|
+
* @returns {Array<(...args: Events[K]) => unknown>}
|
|
131
|
+
*/
|
|
132
|
+
listeners<K extends keyof Events & string>(event: K): Array<(...args: Events[K]) => unknown>;
|
|
133
|
+
/**
|
|
134
|
+
* The events that have listeners.
|
|
135
|
+
*
|
|
136
|
+
* @returns {Array<keyof Events & string>}
|
|
137
|
+
*/
|
|
138
|
+
eventNames(): Array<keyof Events & string>;
|
|
139
|
+
/**
|
|
140
|
+
* Removes all listeners of an event, or everything if you don't name one.
|
|
141
|
+
*
|
|
142
|
+
* @param {keyof Events & string} [event]
|
|
143
|
+
* @returns {this}
|
|
144
|
+
*/
|
|
145
|
+
clear(event?: keyof Events & string): this;
|
|
146
|
+
#private;
|
|
147
|
+
}
|
|
148
|
+
declare namespace Emitter {
|
|
149
|
+
export { EventMap, ListenOptions, WaitForOptions, _StoredListener };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Event names mapped to their arguments, like
|
|
153
|
+
* `{ ready: [], data: [chunk: Buffer], error: [error: Error] }`.
|
|
154
|
+
*/
|
|
155
|
+
type EventMap = Record<string, any[]>;
|
|
156
|
+
/**
|
|
157
|
+
* Options for `on()` and `once()`.
|
|
158
|
+
*/
|
|
159
|
+
type ListenOptions = {
|
|
160
|
+
/**
|
|
161
|
+
* Removes the listener when aborted. One signal can clean up many listeners at once.
|
|
162
|
+
*/
|
|
163
|
+
signal?: AbortSignal | undefined;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Options for `waitFor()`.
|
|
167
|
+
*/
|
|
168
|
+
type WaitForOptions<A extends any[]> = {
|
|
169
|
+
/**
|
|
170
|
+
* Reject with a `TimeoutError` after this long.
|
|
171
|
+
*/
|
|
172
|
+
timeout?: string | number | undefined;
|
|
173
|
+
/**
|
|
174
|
+
* Reject with an `AbortError` when aborted.
|
|
175
|
+
*/
|
|
176
|
+
signal?: AbortSignal | undefined;
|
|
177
|
+
/**
|
|
178
|
+
* Only resolve for events that pass this test.
|
|
179
|
+
*/
|
|
180
|
+
filter?: ((...args: A) => boolean) | undefined;
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* A listener as stored: `once()` wraps the function it was given and keeps
|
|
184
|
+
* it as `listener`, so `off()` can find it.
|
|
185
|
+
*/
|
|
186
|
+
type _StoredListener = ((...args: any[]) => unknown) & {
|
|
187
|
+
listener?: Function;
|
|
188
|
+
};
|
|
189
|
+
//# sourceMappingURL=Emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Emitter.d.ts","sourceRoot":"","sources":["../../src/Emitter.js"],"names":[],"mappings":";AAiDA;;;;;GAKG;AACH,sBAFyB,MAAM,SAAjB,QAAS;IA0CrB;;;;;;;;;;;;;;;;;OAiBG;IACH,GANqC,CAAC,SAAxB,MAAM,MAAM,GAAG,MAAO,SACzB,CAAC,YACD,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,YAC/B,aAAa,GACX,MAAM,IAAI,CAItB;IAED;;;;;;;;OAQG;IACH,KANqC,CAAC,SAAxB,MAAM,MAAM,GAAG,MAAO,SACzB,CAAC,YACD,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,YAC/B,aAAa,GACX,MAAM,IAAI,CAWtB;IAED;;;;;;;;;OASG;IACH,gBAHW,CAAC,KAAK,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,GACvD,MAAM,IAAI,CAOtB;IAED;;;;;;;OAOG;IACH,IALqC,CAAC,SAAxB,MAAM,MAAM,GAAG,MAAO,SACzB,CAAC,aACD,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,GAC7B,IAAI,CAMhB;IAED;;;;;;;;;;;OAWG;IACH,KALqC,CAAC,SAAxB,MAAM,MAAM,GAAG,MAAO,SACzB,CAAC,WACD,MAAM,CAAC,CAAC,CAAC,GACP,OAAO,CAQnB;IAED;;;;;;;;;;;OAWG;IACH,UALqC,CAAC,SAAxB,MAAM,MAAM,GAAG,MAAO,SACzB,CAAC,WACD,MAAM,CAAC,CAAC,CAAC,GACP,OAAO,CAAC,OAAO,EAAE,CAAC,CAQ9B;IAED;;;;;;;;;;;;;OAaG;IACH,QAPqC,CAAC,SAAxB,MAAM,MAAM,GAAG,MAAO,SACzB,CAAC,YACD,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAgC9B;IAED;;;;;;;;;;;;;OAaG;IACH,QALqC,CAAC,SAAxB,MAAM,MAAM,GAAG,MAAO,SACzB,CAAC,YACD;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GACtB,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAsC5C;IAED;;;;;;OAMG;IACH,sBAHW,MAAM,MAAM,GAAG,MAAM,GACnB,MAAM,CAOlB;IAED;;;;;;;OAOG;IACH,UAJqC,CAAC,SAAxB,MAAM,MAAM,GAAG,MAAO,SACzB,CAAC,GACC,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAIlD;IAED;;;;OAIG;IACH,cAFa,KAAK,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,CAIxC;IAED;;;;;OAKG;IACH,cAHW,MAAM,MAAM,GAAG,MAAM,GACnB,IAAI,CAShB;;CACF;;;;;;;;gBA3UY,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;;;;;;;;;;;;;oBAWb,CAAC,SAAR,GAAG,EAAG;;;;;;;;;;;;wBAII,CAAC,KAAK,OAAO;;;;;;uBAMxB,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG;IAAE,QAAQ,CAAC,WAAU;CAAE"}
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
declare namespace _exports {
|
|
2
|
+
export { EnvLoadOptions, EnvParseOptions, EnvGetterOptions, EnvVarSpec, EnvVarValue, EnvConfig };
|
|
3
|
+
}
|
|
4
|
+
declare namespace _exports {
|
|
5
|
+
export { parse };
|
|
6
|
+
export { load };
|
|
7
|
+
export { get };
|
|
8
|
+
export { has };
|
|
9
|
+
export { required };
|
|
10
|
+
export { string };
|
|
11
|
+
export { number };
|
|
12
|
+
export { bool };
|
|
13
|
+
export { port };
|
|
14
|
+
export { url };
|
|
15
|
+
export { duration };
|
|
16
|
+
export { list };
|
|
17
|
+
export { json };
|
|
18
|
+
export { oneOf };
|
|
19
|
+
export { validate };
|
|
20
|
+
export { example };
|
|
21
|
+
export { mode };
|
|
22
|
+
export { isProduction };
|
|
23
|
+
export { isDevelopment };
|
|
24
|
+
export { isTest };
|
|
25
|
+
}
|
|
26
|
+
export = _exports;
|
|
27
|
+
/**
|
|
28
|
+
* Options for `load()`.
|
|
29
|
+
*/
|
|
30
|
+
type EnvLoadOptions = {
|
|
31
|
+
/**
|
|
32
|
+
* Overwrite variables that are already set.
|
|
33
|
+
*/
|
|
34
|
+
override?: boolean | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Replace `${OTHER}` references. Defaults to `true`.
|
|
37
|
+
*/
|
|
38
|
+
expand?: boolean | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Throw if a file is missing.
|
|
41
|
+
*/
|
|
42
|
+
required?: boolean | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Also load the files that go with each one: `.env.production.local`, `.env.local`, `.env.production`, then `.env`. `true` takes the mode from `NODE_ENV`; a string names it. `.env.local` is skipped in test mode, so tests run the same for everyone.
|
|
45
|
+
*/
|
|
46
|
+
cascade?: string | boolean | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Where to put the variables. Defaults to `process.env`.
|
|
49
|
+
*/
|
|
50
|
+
target?: NodeJS.ProcessEnv | undefined;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Options for `parse()`.
|
|
54
|
+
*/
|
|
55
|
+
type EnvParseOptions = {
|
|
56
|
+
/**
|
|
57
|
+
* Replace `$VAR`, `${VAR}` and `${VAR:-default}`. Defaults to `true`.
|
|
58
|
+
*/
|
|
59
|
+
expand?: boolean | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Other variables usable in expansions. Defaults to `process.env`.
|
|
62
|
+
*/
|
|
63
|
+
env?: Record<string, string | undefined> | undefined;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Options shared by the typed getters.
|
|
67
|
+
*/
|
|
68
|
+
type EnvGetterOptions<T> = {
|
|
69
|
+
/**
|
|
70
|
+
* Used when the variable is missing or empty. Without it, the variable is required.
|
|
71
|
+
*/
|
|
72
|
+
default?: T | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Return `undefined` instead of throwing when it's missing.
|
|
75
|
+
*/
|
|
76
|
+
optional?: boolean | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Where to read from. Defaults to `process.env`.
|
|
79
|
+
*/
|
|
80
|
+
env?: NodeJS.ProcessEnv | undefined;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* One variable in `validate()`. It's required unless it has a `default` or
|
|
84
|
+
* `optional: true`.
|
|
85
|
+
*/
|
|
86
|
+
type EnvVarSpec = ({
|
|
87
|
+
type: "string";
|
|
88
|
+
default?: string;
|
|
89
|
+
optional?: boolean;
|
|
90
|
+
pattern?: RegExp;
|
|
91
|
+
minLength?: number;
|
|
92
|
+
description?: string;
|
|
93
|
+
} | {
|
|
94
|
+
type: "number";
|
|
95
|
+
default?: number;
|
|
96
|
+
optional?: boolean;
|
|
97
|
+
min?: number;
|
|
98
|
+
max?: number;
|
|
99
|
+
integer?: boolean;
|
|
100
|
+
description?: string;
|
|
101
|
+
} | {
|
|
102
|
+
type: "boolean";
|
|
103
|
+
default?: boolean;
|
|
104
|
+
optional?: boolean;
|
|
105
|
+
description?: string;
|
|
106
|
+
} | {
|
|
107
|
+
type: "port";
|
|
108
|
+
default?: number;
|
|
109
|
+
optional?: boolean;
|
|
110
|
+
description?: string;
|
|
111
|
+
} | {
|
|
112
|
+
type: "url";
|
|
113
|
+
default?: string;
|
|
114
|
+
optional?: boolean;
|
|
115
|
+
protocols?: string[];
|
|
116
|
+
description?: string;
|
|
117
|
+
} | {
|
|
118
|
+
type: "email";
|
|
119
|
+
default?: string;
|
|
120
|
+
optional?: boolean;
|
|
121
|
+
description?: string;
|
|
122
|
+
} | {
|
|
123
|
+
type: "duration";
|
|
124
|
+
default?: number | string;
|
|
125
|
+
optional?: boolean;
|
|
126
|
+
description?: string;
|
|
127
|
+
} | {
|
|
128
|
+
type: "list";
|
|
129
|
+
default?: string[];
|
|
130
|
+
optional?: boolean;
|
|
131
|
+
separator?: string;
|
|
132
|
+
description?: string;
|
|
133
|
+
} | {
|
|
134
|
+
type: "json";
|
|
135
|
+
default?: unknown;
|
|
136
|
+
optional?: boolean;
|
|
137
|
+
description?: string;
|
|
138
|
+
} | {
|
|
139
|
+
type: "enum";
|
|
140
|
+
values: readonly string[];
|
|
141
|
+
default?: string;
|
|
142
|
+
optional?: boolean;
|
|
143
|
+
description?: string;
|
|
144
|
+
});
|
|
145
|
+
/**
|
|
146
|
+
* The type a variable gets once read.
|
|
147
|
+
*/
|
|
148
|
+
type EnvVarValue<S extends EnvVarSpec> = S["type"] extends "number" | "port" | "duration" ? number : S["type"] extends "boolean" ? boolean : S["type"] extends "list" ? string[] : S["type"] extends "json" ? any : S extends {
|
|
149
|
+
values: readonly (infer V)[];
|
|
150
|
+
} ? V : string;
|
|
151
|
+
/**
|
|
152
|
+
* What `validate()` returns.
|
|
153
|
+
*/
|
|
154
|
+
type EnvConfig<T extends Record<string, EnvVarSpec>> = { -readonly [K in keyof T]: T[K] extends {
|
|
155
|
+
optional: true;
|
|
156
|
+
} ? EnvVarValue<T[K]> | undefined : EnvVarValue<T[K]>; };
|
|
157
|
+
/**
|
|
158
|
+
* Parses the text of a `.env` file: quotes, multi-line values, `export`,
|
|
159
|
+
* comments, escapes, and `${VAR}` expansion (except in single quotes).
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* env.parse('PORT=3000\nURL="http://localhost:${PORT}"');
|
|
163
|
+
* // { PORT: "3000", URL: "http://localhost:3000" }
|
|
164
|
+
*
|
|
165
|
+
* @param {string} content
|
|
166
|
+
* @param {EnvParseOptions} [options]
|
|
167
|
+
* @returns {Record<string, string>}
|
|
168
|
+
*/
|
|
169
|
+
declare function parse(content: string, options?: EnvParseOptions): Record<string, string>;
|
|
170
|
+
/**
|
|
171
|
+
* Loads `.env` files into `process.env`. The first file to set a variable
|
|
172
|
+
* wins, and variables that are already set are kept, unless you pass
|
|
173
|
+
* `override`. The `.env` loaded by itself at startup doesn't count as
|
|
174
|
+
* already set: `.env.local` wins over it, as you'd expect.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* env.load(); // ./.env
|
|
178
|
+
* env.load([".env.local", ".env"]); // local values win
|
|
179
|
+
* env.load(".env.test", { override: true });
|
|
180
|
+
* env.load(".env", { cascade: true }); // .env.production.local, .env.local, .env.production, .env
|
|
181
|
+
*
|
|
182
|
+
* @param {string | string[]} [files=".env"] Relative to the working directory.
|
|
183
|
+
* @param {EnvLoadOptions} [options]
|
|
184
|
+
* @returns {Record<string, string>} Everything read from the files.
|
|
185
|
+
* @throws {Error} If `required` is set and a file is missing.
|
|
186
|
+
*/
|
|
187
|
+
declare function load(files?: string | string[], options?: EnvLoadOptions): Record<string, string>;
|
|
188
|
+
/**
|
|
189
|
+
* Reads a variable, with a fallback. Never throws.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* env.get("REGION", "eu-west-1");
|
|
193
|
+
*
|
|
194
|
+
* @param {string} name
|
|
195
|
+
* @param {string} [fallback]
|
|
196
|
+
* @returns {string | undefined}
|
|
197
|
+
*/
|
|
198
|
+
declare function get(name: string, fallback?: string): string | undefined;
|
|
199
|
+
/**
|
|
200
|
+
* Is the variable set, even to an empty string?
|
|
201
|
+
*
|
|
202
|
+
* @param {string} name
|
|
203
|
+
* @returns {boolean}
|
|
204
|
+
*/
|
|
205
|
+
declare function has(name: string): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Reads a variable that must be set and not empty.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* const key = env.required("STRIPE_SECRET_KEY");
|
|
211
|
+
*
|
|
212
|
+
* @param {string} name
|
|
213
|
+
* @returns {string}
|
|
214
|
+
* @throws {ValidationError} If it's missing or empty.
|
|
215
|
+
*/
|
|
216
|
+
declare function required(name: string): string;
|
|
217
|
+
/**
|
|
218
|
+
* Reads a string. Required unless you give a default or `optional`.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* env.string("APP_NAME", { default: "my-app" });
|
|
222
|
+
*
|
|
223
|
+
* @param {string} name
|
|
224
|
+
* @param {EnvGetterOptions<string> & { pattern?: RegExp, minLength?: number }} [options]
|
|
225
|
+
* @returns {string}
|
|
226
|
+
* @throws {ValidationError}
|
|
227
|
+
*/
|
|
228
|
+
declare function string(name: string, options?: EnvGetterOptions<string> & {
|
|
229
|
+
pattern?: RegExp;
|
|
230
|
+
minLength?: number;
|
|
231
|
+
}): string;
|
|
232
|
+
/**
|
|
233
|
+
* Reads a number.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* env.number("WORKERS", { default: 4, min: 1, integer: true });
|
|
237
|
+
*
|
|
238
|
+
* @param {string} name
|
|
239
|
+
* @param {EnvGetterOptions<number> & { min?: number, max?: number, integer?: boolean }} [options]
|
|
240
|
+
* @returns {number}
|
|
241
|
+
* @throws {ValidationError}
|
|
242
|
+
*/
|
|
243
|
+
declare function number(name: string, options?: EnvGetterOptions<number> & {
|
|
244
|
+
min?: number;
|
|
245
|
+
max?: number;
|
|
246
|
+
integer?: boolean;
|
|
247
|
+
}): number;
|
|
248
|
+
/**
|
|
249
|
+
* Reads a boolean: `true`/`false`, `1`/`0`, `yes`/`no` or `on`/`off`.
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* if (env.bool("FEATURE_BETA", { default: false })) enableBeta();
|
|
253
|
+
*
|
|
254
|
+
* @param {string} name
|
|
255
|
+
* @param {EnvGetterOptions<boolean>} [options]
|
|
256
|
+
* @returns {boolean}
|
|
257
|
+
* @throws {ValidationError}
|
|
258
|
+
*/
|
|
259
|
+
declare function bool(name: string, options?: EnvGetterOptions<boolean>): boolean;
|
|
260
|
+
/**
|
|
261
|
+
* Reads a port number.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* server.listen(env.port("PORT", { default: 3000 }));
|
|
265
|
+
*
|
|
266
|
+
* @param {string} name
|
|
267
|
+
* @param {EnvGetterOptions<number>} [options]
|
|
268
|
+
* @returns {number}
|
|
269
|
+
* @throws {ValidationError}
|
|
270
|
+
*/
|
|
271
|
+
declare function port(name: string, options?: EnvGetterOptions<number>): number;
|
|
272
|
+
/**
|
|
273
|
+
* Reads an absolute URL.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* env.url("DATABASE_URL", { protocols: ["postgres", "postgresql"] });
|
|
277
|
+
*
|
|
278
|
+
* @param {string} name
|
|
279
|
+
* @param {EnvGetterOptions<string> & { protocols?: string[] }} [options]
|
|
280
|
+
* @returns {string}
|
|
281
|
+
* @throws {ValidationError}
|
|
282
|
+
*/
|
|
283
|
+
declare function url(name: string, options?: EnvGetterOptions<string> & {
|
|
284
|
+
protocols?: string[];
|
|
285
|
+
}): string;
|
|
286
|
+
/**
|
|
287
|
+
* Reads a duration like `"30s"` or `"1h30m"` and returns milliseconds.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* env.duration("CACHE_TTL", { default: "10m" }); // 600000
|
|
291
|
+
*
|
|
292
|
+
* @param {string} name
|
|
293
|
+
* @param {EnvGetterOptions<number | string>} [options]
|
|
294
|
+
* @returns {number}
|
|
295
|
+
* @throws {ValidationError}
|
|
296
|
+
*/
|
|
297
|
+
declare function duration(name: string, options?: EnvGetterOptions<number | string>): number;
|
|
298
|
+
/**
|
|
299
|
+
* Reads a comma-separated list. Items are trimmed and empty ones dropped.
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* // ALLOWED_ORIGINS="https://a.com, https://b.com"
|
|
303
|
+
* env.list("ALLOWED_ORIGINS", { default: [] }); // ["https://a.com", "https://b.com"]
|
|
304
|
+
*
|
|
305
|
+
* @param {string} name
|
|
306
|
+
* @param {EnvGetterOptions<string[]> & { separator?: string }} [options]
|
|
307
|
+
* @returns {string[]}
|
|
308
|
+
* @throws {ValidationError}
|
|
309
|
+
*/
|
|
310
|
+
declare function list(name: string, options?: EnvGetterOptions<string[]> & {
|
|
311
|
+
separator?: string;
|
|
312
|
+
}): string[];
|
|
313
|
+
/**
|
|
314
|
+
* Reads a JSON value.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* const flags = env.json("FEATURE_FLAGS", { default: {} });
|
|
318
|
+
*
|
|
319
|
+
* @template [T=any]
|
|
320
|
+
* @param {string} name
|
|
321
|
+
* @param {EnvGetterOptions<T>} [options]
|
|
322
|
+
* @returns {T}
|
|
323
|
+
* @throws {ValidationError}
|
|
324
|
+
*/
|
|
325
|
+
declare function json<T = any>(name: string, options?: EnvGetterOptions<T>): T;
|
|
326
|
+
/**
|
|
327
|
+
* Reads a variable that must be one of the given values. The result has
|
|
328
|
+
* their literal type.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* env.oneOf("LOG_LEVEL", ["debug", "info", "warn", "error"], { default: "info" });
|
|
332
|
+
*
|
|
333
|
+
* @template {string} V
|
|
334
|
+
* @param {string} name
|
|
335
|
+
* @param {readonly V[]} values
|
|
336
|
+
* @param {EnvGetterOptions<V>} [options]
|
|
337
|
+
* @returns {V}
|
|
338
|
+
* @throws {ValidationError}
|
|
339
|
+
*/
|
|
340
|
+
declare function oneOf<V extends string>(name: string, values: readonly V[], options?: EnvGetterOptions<V>): V;
|
|
341
|
+
/**
|
|
342
|
+
* Checks all your variables at once and returns a typed, frozen config. If
|
|
343
|
+
* anything is wrong, one `ValidationError` lists every problem, so a bad
|
|
344
|
+
* deployment fails at startup with the full picture.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* const config = env.validate({
|
|
348
|
+
* NODE_ENV: { type: "enum", values: ["development", "production", "test"], default: "development" },
|
|
349
|
+
* PORT: { type: "port", default: 3000 },
|
|
350
|
+
* DATABASE_URL: { type: "url", protocols: ["postgres"] },
|
|
351
|
+
* JWT_SECRET: { type: "string", minLength: 32 },
|
|
352
|
+
* SENTRY_DSN: { type: "url", optional: true },
|
|
353
|
+
* });
|
|
354
|
+
* // ValidationError: Validation failed with 2 issues:
|
|
355
|
+
* // • DATABASE_URL: is required but is not set
|
|
356
|
+
* // • JWT_SECRET: must contain at least 32 characters
|
|
357
|
+
*
|
|
358
|
+
* @template {Record<string, EnvVarSpec>} T
|
|
359
|
+
* @param {T} spec
|
|
360
|
+
* @param {{ env?: NodeJS.ProcessEnv }} [options]
|
|
361
|
+
* @returns {Readonly<EnvConfig<T>>}
|
|
362
|
+
* @throws {ValidationError}
|
|
363
|
+
*/
|
|
364
|
+
declare function validate<T extends Record<string, EnvVarSpec>>(spec: T, options?: {
|
|
365
|
+
env?: NodeJS.ProcessEnv;
|
|
366
|
+
}): Readonly<EnvConfig<T>>;
|
|
367
|
+
/**
|
|
368
|
+
* Writes the `.env.example` that goes with a `validate()` spec: one entry
|
|
369
|
+
* per variable, with its description, type and default. Keep the file in
|
|
370
|
+
* the repository so nobody has to read the code to know what to set.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* const spec = {
|
|
374
|
+
* PORT: { type: "port", default: 3000, description: "Port to listen on" },
|
|
375
|
+
* DATABASE_URL: { type: "url", description: "Postgres connection string" },
|
|
376
|
+
* };
|
|
377
|
+
* fs.writeFileSync(".env.example", env.example(spec));
|
|
378
|
+
* // # Port to listen on
|
|
379
|
+
* // # port, default: 3000
|
|
380
|
+
* // PORT=3000
|
|
381
|
+
* //
|
|
382
|
+
* // # Postgres connection string
|
|
383
|
+
* // # url, required
|
|
384
|
+
* // DATABASE_URL=
|
|
385
|
+
*
|
|
386
|
+
* @param {Record<string, EnvVarSpec>} spec
|
|
387
|
+
* @returns {string}
|
|
388
|
+
*/
|
|
389
|
+
declare function example(spec: Record<string, EnvVarSpec>): string;
|
|
390
|
+
/**
|
|
391
|
+
* `NODE_ENV`, or `"development"` when it's not set.
|
|
392
|
+
*
|
|
393
|
+
* @returns {string}
|
|
394
|
+
*/
|
|
395
|
+
declare function mode(): string;
|
|
396
|
+
/**
|
|
397
|
+
* Is `NODE_ENV` set to `"production"`?
|
|
398
|
+
* @returns {boolean}
|
|
399
|
+
*/
|
|
400
|
+
declare function isProduction(): boolean;
|
|
401
|
+
/**
|
|
402
|
+
* Is `NODE_ENV` `"development"`, or not set?
|
|
403
|
+
* @returns {boolean}
|
|
404
|
+
*/
|
|
405
|
+
declare function isDevelopment(): boolean;
|
|
406
|
+
/**
|
|
407
|
+
* Are we running tests? True when `NODE_ENV` is `"test"` or a test runner
|
|
408
|
+
* like `node --test` or Jest is detected.
|
|
409
|
+
* @returns {boolean}
|
|
410
|
+
*/
|
|
411
|
+
declare function isTest(): boolean;
|
|
412
|
+
//# sourceMappingURL=Env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Env.d.ts","sourceRoot":"","sources":["../../src/Env.js"],"names":[],"mappings":"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"}
|