typed-settings 0.1.0 → 0.1.4
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 +4 -2
- package/dist/adapters/joi.d.cts +13 -0
- package/dist/adapters/joi.d.ts +13 -0
- package/dist/adapters/zod.d.cts +16 -0
- package/dist/adapters/zod.d.ts +16 -0
- package/dist/{chunk-VTIYOSG2.js → chunk-DEP5SD4J.js} +1 -1
- package/dist/{chunk-RCO6K3WQ.js → chunk-YVJEZPPZ.js} +11 -6
- package/dist/cli/main.cjs +11 -6
- package/dist/cli/main.d.cts +4 -0
- package/dist/cli/main.d.ts +4 -0
- package/dist/cli/main.js +2 -2
- package/dist/{errors-IU9n4f3t.d.cts → errors-itGaU4Q8.d.cts} +5 -0
- package/dist/{errors-IU9n4f3t.d.ts → errors-itGaU4Q8.d.ts} +5 -0
- package/dist/formats/env.d.cts +5 -0
- package/dist/formats/env.d.ts +5 -0
- package/dist/formats/json.d.cts +4 -0
- package/dist/formats/json.d.ts +4 -0
- package/dist/formats/toml.d.cts +4 -0
- package/dist/formats/toml.d.ts +4 -0
- package/dist/formats/yaml.d.cts +5 -0
- package/dist/formats/yaml.d.ts +5 -0
- package/dist/framework/next.cjs +11 -6
- package/dist/framework/next.d.cts +16 -3
- package/dist/framework/next.d.ts +16 -3
- package/dist/framework/next.js +1 -1
- package/dist/framework/vite.cjs +11 -6
- package/dist/framework/vite.d.cts +16 -3
- package/dist/framework/vite.d.ts +16 -3
- package/dist/framework/vite.js +2 -2
- package/dist/index.cjs +11 -6
- package/dist/index.d.cts +42 -3
- package/dist/index.d.ts +42 -3
- package/dist/index.js +1 -1
- package/dist/node.cjs +11 -6
- package/dist/node.d.cts +29 -2
- package/dist/node.d.ts +29 -2
- package/dist/node.js +2 -2
- package/dist/{shared-DBcV6jIy.d.cts → shared-CucO_XsG.d.cts} +1 -0
- package/dist/{shared-DBcV6jIy.d.ts → shared-CucO_XsG.d.ts} +1 -0
- package/dist/types-B_Dc2L4T.d.cts +69 -0
- package/dist/types-B_Dc2L4T.d.ts +69 -0
- package/dist/vault/aws.d.cts +26 -1
- package/dist/vault/aws.d.ts +26 -1
- package/dist/vault/hashicorp.d.cts +23 -2
- package/dist/vault/hashicorp.d.ts +23 -2
- package/dist/vault/http.d.cts +20 -2
- package/dist/vault/http.d.ts +20 -2
- package/package.json +9 -1
- package/dist/types-BswIPp7U.d.cts +0 -41
- package/dist/types-BswIPp7U.d.ts +0 -41
package/dist/index.d.cts
CHANGED
|
@@ -1,12 +1,51 @@
|
|
|
1
1
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
-
import { S as SettingsOptions, F as Flat } from './types-
|
|
3
|
-
export { A as ArrayStrategy, a as SecretProvider, b as SourceInput, U as UnknownKeys } from './types-
|
|
4
|
-
export { C as ConfigError } from './errors-
|
|
2
|
+
import { S as SettingsOptions, F as Flat } from './types-B_Dc2L4T.cjs';
|
|
3
|
+
export { A as ArrayStrategy, a as SecretProvider, b as SourceInput, U as UnknownKeys } from './types-B_Dc2L4T.cjs';
|
|
4
|
+
export { C as ConfigError } from './errors-itGaU4Q8.cjs';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Typed config in one call.
|
|
8
|
+
*
|
|
9
|
+
* `settings()` / `settingsAsync()` load env, `.env` files, YAML/TOML/JSON,
|
|
10
|
+
* secrets-dir maps, and vault secrets, then merge, expand `$VAR` references,
|
|
11
|
+
* coerce, validate against a Standard Schema, and return the result frozen.
|
|
12
|
+
* Anything invalid throws `ConfigError` at boot with the key and source attached.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Runs `fn` with `process.env` patched by `map` (`undefined` deletes a key),
|
|
19
|
+
* then restores the exact previous environment — synchronously for sync `fn`,
|
|
20
|
+
* held until settle for async `fn`. Restores on throw too.
|
|
21
|
+
*/
|
|
6
22
|
declare function withOverrides<T>(map: Flat, fn: () => T): T;
|
|
23
|
+
/**
|
|
24
|
+
* Copies only the listed, actually-present keys. A missing key yields no entry
|
|
25
|
+
* (not `{ k: undefined }`), and nothing is spread, so secrets can't leak through.
|
|
26
|
+
*/
|
|
7
27
|
declare function pickPublic<T extends object>(cfg: T, keys: (keyof T)[]): Partial<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Map-only settings for Vite-style `import.meta.env` objects: validates the
|
|
30
|
+
* map with no filesystem and no ambient env. (The framework entry's overload
|
|
31
|
+
* drops `sources`/`env` from the options.)
|
|
32
|
+
*/
|
|
8
33
|
declare function viteSettings<S extends StandardSchemaV1>(opts: SettingsOptions<S>, metaEnv: Flat): StandardSchemaV1.InferOutput<S>;
|
|
34
|
+
/**
|
|
35
|
+
* Loads, merges, expands, coerces, and validates config synchronously, returning
|
|
36
|
+
* the inferred output type, frozen. Each issue names the failing `path` and the
|
|
37
|
+
* source that won it, with secrets redacted.
|
|
38
|
+
*
|
|
39
|
+
* @throws ConfigError on merge, parse, expansion, or validation failure.
|
|
40
|
+
* @throws ConfigError with `code: 'USE_ASYNC'` if a provider or the schema is
|
|
41
|
+
* async — switch to `settingsAsync()`.
|
|
42
|
+
*/
|
|
9
43
|
declare function settings<S extends StandardSchemaV1>(opts: SettingsOptions<S>): StandardSchemaV1.InferOutput<S>;
|
|
44
|
+
/**
|
|
45
|
+
* Async twin of `settings()`: awaits async providers (whole collection races
|
|
46
|
+
* `timeoutMs`) and async schemas, with the same merge/expand/coerce/validate/
|
|
47
|
+
* freeze pipeline and the same `ConfigError` contract.
|
|
48
|
+
*/
|
|
10
49
|
declare function settingsAsync<S extends StandardSchemaV1>(opts: SettingsOptions<S>): Promise<StandardSchemaV1.InferOutput<S>>;
|
|
11
50
|
|
|
12
51
|
export { Flat, SettingsOptions, pickPublic, settings, settingsAsync, viteSettings, withOverrides };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,51 @@
|
|
|
1
1
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
-
import { S as SettingsOptions, F as Flat } from './types-
|
|
3
|
-
export { A as ArrayStrategy, a as SecretProvider, b as SourceInput, U as UnknownKeys } from './types-
|
|
4
|
-
export { C as ConfigError } from './errors-
|
|
2
|
+
import { S as SettingsOptions, F as Flat } from './types-B_Dc2L4T.js';
|
|
3
|
+
export { A as ArrayStrategy, a as SecretProvider, b as SourceInput, U as UnknownKeys } from './types-B_Dc2L4T.js';
|
|
4
|
+
export { C as ConfigError } from './errors-itGaU4Q8.js';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Typed config in one call.
|
|
8
|
+
*
|
|
9
|
+
* `settings()` / `settingsAsync()` load env, `.env` files, YAML/TOML/JSON,
|
|
10
|
+
* secrets-dir maps, and vault secrets, then merge, expand `$VAR` references,
|
|
11
|
+
* coerce, validate against a Standard Schema, and return the result frozen.
|
|
12
|
+
* Anything invalid throws `ConfigError` at boot with the key and source attached.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Runs `fn` with `process.env` patched by `map` (`undefined` deletes a key),
|
|
19
|
+
* then restores the exact previous environment — synchronously for sync `fn`,
|
|
20
|
+
* held until settle for async `fn`. Restores on throw too.
|
|
21
|
+
*/
|
|
6
22
|
declare function withOverrides<T>(map: Flat, fn: () => T): T;
|
|
23
|
+
/**
|
|
24
|
+
* Copies only the listed, actually-present keys. A missing key yields no entry
|
|
25
|
+
* (not `{ k: undefined }`), and nothing is spread, so secrets can't leak through.
|
|
26
|
+
*/
|
|
7
27
|
declare function pickPublic<T extends object>(cfg: T, keys: (keyof T)[]): Partial<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Map-only settings for Vite-style `import.meta.env` objects: validates the
|
|
30
|
+
* map with no filesystem and no ambient env. (The framework entry's overload
|
|
31
|
+
* drops `sources`/`env` from the options.)
|
|
32
|
+
*/
|
|
8
33
|
declare function viteSettings<S extends StandardSchemaV1>(opts: SettingsOptions<S>, metaEnv: Flat): StandardSchemaV1.InferOutput<S>;
|
|
34
|
+
/**
|
|
35
|
+
* Loads, merges, expands, coerces, and validates config synchronously, returning
|
|
36
|
+
* the inferred output type, frozen. Each issue names the failing `path` and the
|
|
37
|
+
* source that won it, with secrets redacted.
|
|
38
|
+
*
|
|
39
|
+
* @throws ConfigError on merge, parse, expansion, or validation failure.
|
|
40
|
+
* @throws ConfigError with `code: 'USE_ASYNC'` if a provider or the schema is
|
|
41
|
+
* async — switch to `settingsAsync()`.
|
|
42
|
+
*/
|
|
9
43
|
declare function settings<S extends StandardSchemaV1>(opts: SettingsOptions<S>): StandardSchemaV1.InferOutput<S>;
|
|
44
|
+
/**
|
|
45
|
+
* Async twin of `settings()`: awaits async providers (whole collection races
|
|
46
|
+
* `timeoutMs`) and async schemas, with the same merge/expand/coerce/validate/
|
|
47
|
+
* freeze pipeline and the same `ConfigError` contract.
|
|
48
|
+
*/
|
|
10
49
|
declare function settingsAsync<S extends StandardSchemaV1>(opts: SettingsOptions<S>): Promise<StandardSchemaV1.InferOutput<S>>;
|
|
11
50
|
|
|
12
51
|
export { Flat, SettingsOptions, pickPublic, settings, settingsAsync, viteSettings, withOverrides };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { pickPublic, settings, settingsAsync, viteSettings, withOverrides } from './chunk-
|
|
1
|
+
export { pickPublic, settings, settingsAsync, viteSettings, withOverrides } from './chunk-YVJEZPPZ.js';
|
|
2
2
|
import './chunk-33M5GIKQ.js';
|
|
3
3
|
import './chunk-OVFMKC2O.js';
|
|
4
4
|
import './chunk-UFUHHR2J.js';
|
package/dist/node.cjs
CHANGED
|
@@ -444,12 +444,12 @@ function expandKeys(flat, opts) {
|
|
|
444
444
|
const stripped = stripPrefix(rawKey);
|
|
445
445
|
if (stripped === null) continue;
|
|
446
446
|
const useKey = stripped;
|
|
447
|
-
if (useKey.
|
|
448
|
-
|
|
449
|
-
|
|
447
|
+
if (FORBIDDEN.has(useKey.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
448
|
+
const parts = useKey.split("__");
|
|
449
|
+
const cleanSplit = parts.length > 1 && parts.every((p) => p !== "");
|
|
450
|
+
if (cleanSplit) {
|
|
450
451
|
for (const p of parts) {
|
|
451
452
|
if (FORBIDDEN.has(p.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
452
|
-
if (!p) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_EMPTY_SEGMENT" }], "E_EMPTY_SEGMENT");
|
|
453
453
|
}
|
|
454
454
|
const lowered = parts.map((p) => p.toLowerCase());
|
|
455
455
|
const top = lowered[0];
|
|
@@ -481,7 +481,6 @@ function expandKeys(flat, opts) {
|
|
|
481
481
|
setPath(out, lowered, value);
|
|
482
482
|
} else {
|
|
483
483
|
const k = useKey.toLowerCase();
|
|
484
|
-
if (FORBIDDEN.has(k)) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO" }], "E_PROTO");
|
|
485
484
|
const kind = kindOf(k);
|
|
486
485
|
if (kind.indexed) {
|
|
487
486
|
throw new ConfigError(
|
|
@@ -861,7 +860,13 @@ function makeLookup(merged, envSnapshot) {
|
|
|
861
860
|
function expandDeepStrings(obj, lookup, ctx, path = []) {
|
|
862
861
|
if (typeof obj === "string") {
|
|
863
862
|
const top = (path[0] ?? "<root>").toLowerCase();
|
|
864
|
-
|
|
863
|
+
const from = ctx.fromMap.get(top) ?? "config";
|
|
864
|
+
try {
|
|
865
|
+
return expandLeaf(obj, lookup, { ...ctx, from }, path.map((p) => p.toLowerCase()));
|
|
866
|
+
} catch (e) {
|
|
867
|
+
if (from === "env") return obj;
|
|
868
|
+
throw e;
|
|
869
|
+
}
|
|
865
870
|
}
|
|
866
871
|
if (Array.isArray(obj)) return obj.map((x, i) => expandDeepStrings(x, lookup, ctx, [...path, String(i)]));
|
|
867
872
|
if (obj && typeof obj === "object") {
|
package/dist/node.d.cts
CHANGED
|
@@ -1,27 +1,54 @@
|
|
|
1
|
-
import { F as Flat, S as SettingsOptions } from './types-
|
|
1
|
+
import { F as Flat, S as SettingsOptions } from './types-B_Dc2L4T.cjs';
|
|
2
2
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
|
-
import { C as ConfigError } from './errors-
|
|
3
|
+
import { C as ConfigError } from './errors-itGaU4Q8.cjs';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Reads dotenv files and joins them with newlines for `{ text }` sources.
|
|
7
|
+
* Missing files are skipped; anything else (e.g. `EACCES`) rethrows.
|
|
8
|
+
*/
|
|
5
9
|
declare function loadEnvFiles(paths: string[]): {
|
|
6
10
|
text: string;
|
|
7
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Reads a secrets dir (Docker/K8s `/run/secrets`) into a flat map keyed by
|
|
14
|
+
* uppercased filenames. Skips subdirectories, `..*` entries, and empties; strips
|
|
15
|
+
* one trailing newline but otherwise preserves whitespace verbatim. Missing dir
|
|
16
|
+
* reads as `{}`; unreadable files throw (`EACCES` fails closed).
|
|
17
|
+
*/
|
|
8
18
|
declare function loadSecretsDir(dir: string): Flat;
|
|
19
|
+
/**
|
|
20
|
+
* Parses one dotenv file into a flat map. Missing file reads as `{}`;
|
|
21
|
+
* anything else (including `EACCES` and syntax errors) rethrows.
|
|
22
|
+
*/
|
|
9
23
|
declare function parseEnvFile(path: string): Flat;
|
|
24
|
+
/** Watch tuning: debounce, provider/dir refresh, stat-poll fallback, and callbacks. */
|
|
10
25
|
interface WatchCallbacks {
|
|
26
|
+
/** Coalesce rapid saves. Default 100. */
|
|
11
27
|
debounceMs?: number;
|
|
28
|
+
/** Re-poll providers/secrets-dirs. Default 0=off (60000 when providers present). */
|
|
12
29
|
refreshMs?: number;
|
|
30
|
+
/** Stat-poll fallback for NFS/Docker where fs events are unreliable. Default 0=off. */
|
|
13
31
|
pollMs?: number;
|
|
32
|
+
/** Fires on each successful reload with the new config and changed leaf paths. */
|
|
14
33
|
onUpdate?: (cfg: unknown, changed: string[]) => void;
|
|
34
|
+
/** Fires when a reload fails; the old config stays live. Never throws outward. */
|
|
15
35
|
onError?: (e: ConfigError | Error, info?: {
|
|
16
36
|
version: number;
|
|
17
37
|
}) => void;
|
|
18
38
|
}
|
|
39
|
+
/** Live config subscription. `reload()` re-reads now; `dispose()` is idempotent. */
|
|
19
40
|
interface WatchHandle<T = unknown> {
|
|
20
41
|
get(): T;
|
|
21
42
|
reload(): Promise<void>;
|
|
22
43
|
dispose(): Promise<void>;
|
|
23
44
|
readonly version: number;
|
|
24
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Subscribes to config files with parent-dir watching (survives atomic renames),
|
|
48
|
+
* debounced reloads, and stable-size settling. Each reload validates off-side and
|
|
49
|
+
* swaps only on success, reporting changed leaf paths; failures keep the old
|
|
50
|
+
* config and notify `onError`. Overlapping reloads drop the stale one.
|
|
51
|
+
*/
|
|
25
52
|
declare function watchSettings<S extends StandardSchemaV1>(opts: SettingsOptions<S>, cb?: WatchCallbacks): WatchHandle<StandardSchemaV1.InferOutput<S>>;
|
|
26
53
|
|
|
27
54
|
export { type WatchCallbacks, type WatchHandle, loadEnvFiles, loadSecretsDir, parseEnvFile, watchSettings };
|
package/dist/node.d.ts
CHANGED
|
@@ -1,27 +1,54 @@
|
|
|
1
|
-
import { F as Flat, S as SettingsOptions } from './types-
|
|
1
|
+
import { F as Flat, S as SettingsOptions } from './types-B_Dc2L4T.js';
|
|
2
2
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
|
-
import { C as ConfigError } from './errors-
|
|
3
|
+
import { C as ConfigError } from './errors-itGaU4Q8.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Reads dotenv files and joins them with newlines for `{ text }` sources.
|
|
7
|
+
* Missing files are skipped; anything else (e.g. `EACCES`) rethrows.
|
|
8
|
+
*/
|
|
5
9
|
declare function loadEnvFiles(paths: string[]): {
|
|
6
10
|
text: string;
|
|
7
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Reads a secrets dir (Docker/K8s `/run/secrets`) into a flat map keyed by
|
|
14
|
+
* uppercased filenames. Skips subdirectories, `..*` entries, and empties; strips
|
|
15
|
+
* one trailing newline but otherwise preserves whitespace verbatim. Missing dir
|
|
16
|
+
* reads as `{}`; unreadable files throw (`EACCES` fails closed).
|
|
17
|
+
*/
|
|
8
18
|
declare function loadSecretsDir(dir: string): Flat;
|
|
19
|
+
/**
|
|
20
|
+
* Parses one dotenv file into a flat map. Missing file reads as `{}`;
|
|
21
|
+
* anything else (including `EACCES` and syntax errors) rethrows.
|
|
22
|
+
*/
|
|
9
23
|
declare function parseEnvFile(path: string): Flat;
|
|
24
|
+
/** Watch tuning: debounce, provider/dir refresh, stat-poll fallback, and callbacks. */
|
|
10
25
|
interface WatchCallbacks {
|
|
26
|
+
/** Coalesce rapid saves. Default 100. */
|
|
11
27
|
debounceMs?: number;
|
|
28
|
+
/** Re-poll providers/secrets-dirs. Default 0=off (60000 when providers present). */
|
|
12
29
|
refreshMs?: number;
|
|
30
|
+
/** Stat-poll fallback for NFS/Docker where fs events are unreliable. Default 0=off. */
|
|
13
31
|
pollMs?: number;
|
|
32
|
+
/** Fires on each successful reload with the new config and changed leaf paths. */
|
|
14
33
|
onUpdate?: (cfg: unknown, changed: string[]) => void;
|
|
34
|
+
/** Fires when a reload fails; the old config stays live. Never throws outward. */
|
|
15
35
|
onError?: (e: ConfigError | Error, info?: {
|
|
16
36
|
version: number;
|
|
17
37
|
}) => void;
|
|
18
38
|
}
|
|
39
|
+
/** Live config subscription. `reload()` re-reads now; `dispose()` is idempotent. */
|
|
19
40
|
interface WatchHandle<T = unknown> {
|
|
20
41
|
get(): T;
|
|
21
42
|
reload(): Promise<void>;
|
|
22
43
|
dispose(): Promise<void>;
|
|
23
44
|
readonly version: number;
|
|
24
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Subscribes to config files with parent-dir watching (survives atomic renames),
|
|
48
|
+
* debounced reloads, and stable-size settling. Each reload validates off-side and
|
|
49
|
+
* swaps only on success, reporting changed leaf paths; failures keep the old
|
|
50
|
+
* config and notify `onError`. Overlapping reloads drop the stale one.
|
|
51
|
+
*/
|
|
25
52
|
declare function watchSettings<S extends StandardSchemaV1>(opts: SettingsOptions<S>, cb?: WatchCallbacks): WatchHandle<StandardSchemaV1.InferOutput<S>>;
|
|
26
53
|
|
|
27
54
|
export { type WatchCallbacks, type WatchHandle, loadEnvFiles, loadSecretsDir, parseEnvFile, watchSettings };
|
package/dist/node.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { loadEnvFiles, loadSecretsDir, parseEnvFile, watchSettings } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
export { loadEnvFiles, loadSecretsDir, parseEnvFile, watchSettings } from './chunk-DEP5SD4J.js';
|
|
2
|
+
import './chunk-YVJEZPPZ.js';
|
|
3
3
|
import './chunk-33M5GIKQ.js';
|
|
4
4
|
import './chunk-OVFMKC2O.js';
|
|
5
5
|
import './chunk-UFUHHR2J.js';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
|
|
3
|
+
/** Flat string map: the currency every source compiles to (`process.env` shape). */
|
|
4
|
+
type Flat = Record<string, string | undefined>;
|
|
5
|
+
/** A secret backend. `load()` may be sync or async; async forces `settingsAsync()`. */
|
|
6
|
+
interface SecretProvider {
|
|
7
|
+
/** Label used in error attribution (`from`) and timeouts. */
|
|
8
|
+
name: string;
|
|
9
|
+
load(): Promise<Flat> | Flat;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* One config source. Strings `'env' | '.env' | '.env.local'` are built-ins,
|
|
13
|
+
* any other string is a file path (relative to cwd; `.json`/`.yaml`/`.yml`/
|
|
14
|
+
* `.toml` are parsed structurally, anything else as `.env` text); objects cover
|
|
15
|
+
* inline text, files, secrets dirs (resolved by the caller), maps, and
|
|
16
|
+
* providers.
|
|
17
|
+
*/
|
|
18
|
+
type SourceInput = 'env' | '.env' | '.env.local' | {
|
|
19
|
+
text: string;
|
|
20
|
+
} | {
|
|
21
|
+
file: string;
|
|
22
|
+
} | {
|
|
23
|
+
dir: string;
|
|
24
|
+
} | {
|
|
25
|
+
map: Flat;
|
|
26
|
+
prefix?: string;
|
|
27
|
+
} | {
|
|
28
|
+
provider: SecretProvider;
|
|
29
|
+
prefix?: string;
|
|
30
|
+
} | SecretProvider | Flat | string;
|
|
31
|
+
/** How arrays merge across layers: wholesale win, append, or per-index union. */
|
|
32
|
+
type ArrayStrategy = 'replace' | 'concat' | 'mergeIndex';
|
|
33
|
+
/** What to do with input keys the schema doesn't declare. */
|
|
34
|
+
type UnknownKeys = 'strip' | 'preserve' | 'reject';
|
|
35
|
+
/** Options for `settings()` / `settingsAsync()`. Full semantics in docs/configuration.md. */
|
|
36
|
+
interface SettingsOptions<S extends StandardSchemaV1 = StandardSchemaV1> {
|
|
37
|
+
/** Validating schema (zod/valibot/arktype natively, yup/joi/superstruct via bridges). */
|
|
38
|
+
schema: S;
|
|
39
|
+
/** Ordered layers, later wins. Default `['.env', 'env']`. */
|
|
40
|
+
sources?: SourceInput[];
|
|
41
|
+
/** Global prefix strip (case-insensitive, once). */
|
|
42
|
+
prefix?: string;
|
|
43
|
+
/** Fixed to `'__'`; only double underscores split keys. */
|
|
44
|
+
separator?: '__';
|
|
45
|
+
/** Best-effort leaf coercion before validation. Default true. */
|
|
46
|
+
coerce?: boolean;
|
|
47
|
+
/** `$VAR` expansion after merging. Default true. */
|
|
48
|
+
expand?: boolean;
|
|
49
|
+
/** Also expand `$VAR` inside vault-provided values. Default false. */
|
|
50
|
+
expandSecrets?: boolean;
|
|
51
|
+
/** Cross-layer array merge. Default 'replace'. */
|
|
52
|
+
arrayStrategy?: ArrayStrategy;
|
|
53
|
+
/** Undeclared keys: drop, keep, or throw. Default 'strip'. */
|
|
54
|
+
unknownKeys?: UnknownKeys;
|
|
55
|
+
/** Deep-freeze the result. Default true. */
|
|
56
|
+
freeze?: boolean;
|
|
57
|
+
/** Async provider + validation timeout in ms. Default 5000, async only. */
|
|
58
|
+
timeoutMs?: number;
|
|
59
|
+
/** Per-file read cap in UTF-8 bytes. Default 2 MiB. */
|
|
60
|
+
maxBytes?: number;
|
|
61
|
+
/** Keys used literally: no prefix strip, no `__` split. */
|
|
62
|
+
envMap?: Record<string, string>;
|
|
63
|
+
/** Keep `${MISSING}` literally instead of throwing. Default false. */
|
|
64
|
+
allowUnresolved?: boolean;
|
|
65
|
+
/** Injectable env snapshot (tests, Edge). Defaults to process.env when available. */
|
|
66
|
+
env?: Flat;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type { ArrayStrategy as A, Flat as F, SettingsOptions as S, UnknownKeys as U, SecretProvider as a, SourceInput as b };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
|
|
3
|
+
/** Flat string map: the currency every source compiles to (`process.env` shape). */
|
|
4
|
+
type Flat = Record<string, string | undefined>;
|
|
5
|
+
/** A secret backend. `load()` may be sync or async; async forces `settingsAsync()`. */
|
|
6
|
+
interface SecretProvider {
|
|
7
|
+
/** Label used in error attribution (`from`) and timeouts. */
|
|
8
|
+
name: string;
|
|
9
|
+
load(): Promise<Flat> | Flat;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* One config source. Strings `'env' | '.env' | '.env.local'` are built-ins,
|
|
13
|
+
* any other string is a file path (relative to cwd; `.json`/`.yaml`/`.yml`/
|
|
14
|
+
* `.toml` are parsed structurally, anything else as `.env` text); objects cover
|
|
15
|
+
* inline text, files, secrets dirs (resolved by the caller), maps, and
|
|
16
|
+
* providers.
|
|
17
|
+
*/
|
|
18
|
+
type SourceInput = 'env' | '.env' | '.env.local' | {
|
|
19
|
+
text: string;
|
|
20
|
+
} | {
|
|
21
|
+
file: string;
|
|
22
|
+
} | {
|
|
23
|
+
dir: string;
|
|
24
|
+
} | {
|
|
25
|
+
map: Flat;
|
|
26
|
+
prefix?: string;
|
|
27
|
+
} | {
|
|
28
|
+
provider: SecretProvider;
|
|
29
|
+
prefix?: string;
|
|
30
|
+
} | SecretProvider | Flat | string;
|
|
31
|
+
/** How arrays merge across layers: wholesale win, append, or per-index union. */
|
|
32
|
+
type ArrayStrategy = 'replace' | 'concat' | 'mergeIndex';
|
|
33
|
+
/** What to do with input keys the schema doesn't declare. */
|
|
34
|
+
type UnknownKeys = 'strip' | 'preserve' | 'reject';
|
|
35
|
+
/** Options for `settings()` / `settingsAsync()`. Full semantics in docs/configuration.md. */
|
|
36
|
+
interface SettingsOptions<S extends StandardSchemaV1 = StandardSchemaV1> {
|
|
37
|
+
/** Validating schema (zod/valibot/arktype natively, yup/joi/superstruct via bridges). */
|
|
38
|
+
schema: S;
|
|
39
|
+
/** Ordered layers, later wins. Default `['.env', 'env']`. */
|
|
40
|
+
sources?: SourceInput[];
|
|
41
|
+
/** Global prefix strip (case-insensitive, once). */
|
|
42
|
+
prefix?: string;
|
|
43
|
+
/** Fixed to `'__'`; only double underscores split keys. */
|
|
44
|
+
separator?: '__';
|
|
45
|
+
/** Best-effort leaf coercion before validation. Default true. */
|
|
46
|
+
coerce?: boolean;
|
|
47
|
+
/** `$VAR` expansion after merging. Default true. */
|
|
48
|
+
expand?: boolean;
|
|
49
|
+
/** Also expand `$VAR` inside vault-provided values. Default false. */
|
|
50
|
+
expandSecrets?: boolean;
|
|
51
|
+
/** Cross-layer array merge. Default 'replace'. */
|
|
52
|
+
arrayStrategy?: ArrayStrategy;
|
|
53
|
+
/** Undeclared keys: drop, keep, or throw. Default 'strip'. */
|
|
54
|
+
unknownKeys?: UnknownKeys;
|
|
55
|
+
/** Deep-freeze the result. Default true. */
|
|
56
|
+
freeze?: boolean;
|
|
57
|
+
/** Async provider + validation timeout in ms. Default 5000, async only. */
|
|
58
|
+
timeoutMs?: number;
|
|
59
|
+
/** Per-file read cap in UTF-8 bytes. Default 2 MiB. */
|
|
60
|
+
maxBytes?: number;
|
|
61
|
+
/** Keys used literally: no prefix strip, no `__` split. */
|
|
62
|
+
envMap?: Record<string, string>;
|
|
63
|
+
/** Keep `${MISSING}` literally instead of throwing. Default false. */
|
|
64
|
+
allowUnresolved?: boolean;
|
|
65
|
+
/** Injectable env snapshot (tests, Edge). Defaults to process.env when available. */
|
|
66
|
+
env?: Flat;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type { ArrayStrategy as A, Flat as F, SettingsOptions as S, UnknownKeys as U, SecretProvider as a, SourceInput as b };
|
package/dist/vault/aws.d.cts
CHANGED
|
@@ -1,26 +1,51 @@
|
|
|
1
|
-
import { a as SecretProvider } from '../types-
|
|
1
|
+
import { a as SecretProvider } from '../types-B_Dc2L4T.cjs';
|
|
2
2
|
import '@standard-schema/spec';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* AWS provider: Secrets Manager ids plus SSM parameters (with decryption)
|
|
6
|
+
* merged into one flat map. SDK clients are injected, never imported blindly,
|
|
7
|
+
* so tests can pass fakes and Edge bundles stay lean.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** Minimal Secrets Manager surface this provider needs (real SDK client or a fake). */
|
|
4
13
|
interface AwsSecretsClient {
|
|
5
14
|
getSecretValue(secretId: string): Promise<{
|
|
6
15
|
SecretString?: string;
|
|
7
16
|
SecretBinary?: Uint8Array | string;
|
|
8
17
|
} | string>;
|
|
9
18
|
}
|
|
19
|
+
/** Minimal SSM surface this provider needs (real SDK client or a fake). */
|
|
10
20
|
interface AwsSsmClient {
|
|
11
21
|
getParameters(names: string[], withDecryption?: boolean): Promise<Record<string, string>>;
|
|
12
22
|
}
|
|
23
|
+
/** Options for {@link awsProvider}. */
|
|
13
24
|
interface AwsProviderOptions {
|
|
25
|
+
/** Secrets Manager ids. */
|
|
14
26
|
secrets?: string[];
|
|
27
|
+
/** SSM names or path prefixes (trailing `/` optional). */
|
|
15
28
|
params?: string[];
|
|
29
|
+
/** Reserved: region override (currently from env `AWS_REGION`). */
|
|
16
30
|
region?: string;
|
|
31
|
+
/** Reserved: VersionId / stage pin. */
|
|
17
32
|
versionId?: string;
|
|
33
|
+
/** Applies to the whole `load()`. Default 5000. */
|
|
18
34
|
timeoutMs?: number;
|
|
35
|
+
/** Injected Secrets Manager client (or test fake); missing throws `E_NO_SDK`. */
|
|
19
36
|
secretsClient?: AwsSecretsClient;
|
|
37
|
+
/** Injected SSM client (or test fake); missing throws `E_NO_SDK`. */
|
|
20
38
|
ssmClient?: AwsSsmClient;
|
|
39
|
+
/** Secrets Manager value cap in bytes. Default 64 KiB. */
|
|
21
40
|
maxBytesSecret?: number;
|
|
41
|
+
/** SSM value cap in bytes. Default 8 KiB. */
|
|
22
42
|
maxBytesParam?: number;
|
|
23
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Merges Secrets Manager values (JSON objects merge, scalars key on the last id
|
|
46
|
+
* segment) with SSM parameters (longest-prefix strip, `/` to `__`, uppercased).
|
|
47
|
+
* Concurrent `load()` calls share one in-flight request.
|
|
48
|
+
*/
|
|
24
49
|
declare function awsProvider(opts: AwsProviderOptions): SecretProvider;
|
|
25
50
|
|
|
26
51
|
export { type AwsProviderOptions, type AwsSecretsClient, type AwsSsmClient, awsProvider };
|
package/dist/vault/aws.d.ts
CHANGED
|
@@ -1,26 +1,51 @@
|
|
|
1
|
-
import { a as SecretProvider } from '../types-
|
|
1
|
+
import { a as SecretProvider } from '../types-B_Dc2L4T.js';
|
|
2
2
|
import '@standard-schema/spec';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* AWS provider: Secrets Manager ids plus SSM parameters (with decryption)
|
|
6
|
+
* merged into one flat map. SDK clients are injected, never imported blindly,
|
|
7
|
+
* so tests can pass fakes and Edge bundles stay lean.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** Minimal Secrets Manager surface this provider needs (real SDK client or a fake). */
|
|
4
13
|
interface AwsSecretsClient {
|
|
5
14
|
getSecretValue(secretId: string): Promise<{
|
|
6
15
|
SecretString?: string;
|
|
7
16
|
SecretBinary?: Uint8Array | string;
|
|
8
17
|
} | string>;
|
|
9
18
|
}
|
|
19
|
+
/** Minimal SSM surface this provider needs (real SDK client or a fake). */
|
|
10
20
|
interface AwsSsmClient {
|
|
11
21
|
getParameters(names: string[], withDecryption?: boolean): Promise<Record<string, string>>;
|
|
12
22
|
}
|
|
23
|
+
/** Options for {@link awsProvider}. */
|
|
13
24
|
interface AwsProviderOptions {
|
|
25
|
+
/** Secrets Manager ids. */
|
|
14
26
|
secrets?: string[];
|
|
27
|
+
/** SSM names or path prefixes (trailing `/` optional). */
|
|
15
28
|
params?: string[];
|
|
29
|
+
/** Reserved: region override (currently from env `AWS_REGION`). */
|
|
16
30
|
region?: string;
|
|
31
|
+
/** Reserved: VersionId / stage pin. */
|
|
17
32
|
versionId?: string;
|
|
33
|
+
/** Applies to the whole `load()`. Default 5000. */
|
|
18
34
|
timeoutMs?: number;
|
|
35
|
+
/** Injected Secrets Manager client (or test fake); missing throws `E_NO_SDK`. */
|
|
19
36
|
secretsClient?: AwsSecretsClient;
|
|
37
|
+
/** Injected SSM client (or test fake); missing throws `E_NO_SDK`. */
|
|
20
38
|
ssmClient?: AwsSsmClient;
|
|
39
|
+
/** Secrets Manager value cap in bytes. Default 64 KiB. */
|
|
21
40
|
maxBytesSecret?: number;
|
|
41
|
+
/** SSM value cap in bytes. Default 8 KiB. */
|
|
22
42
|
maxBytesParam?: number;
|
|
23
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Merges Secrets Manager values (JSON objects merge, scalars key on the last id
|
|
46
|
+
* segment) with SSM parameters (longest-prefix strip, `/` to `__`, uppercased).
|
|
47
|
+
* Concurrent `load()` calls share one in-flight request.
|
|
48
|
+
*/
|
|
24
49
|
declare function awsProvider(opts: AwsProviderOptions): SecretProvider;
|
|
25
50
|
|
|
26
51
|
export { type AwsProviderOptions, type AwsSecretsClient, type AwsSsmClient, awsProvider };
|
|
@@ -1,19 +1,40 @@
|
|
|
1
|
-
import { a as SecretProvider } from '../types-
|
|
2
|
-
import { F as FetchFn } from '../shared-
|
|
1
|
+
import { a as SecretProvider } from '../types-B_Dc2L4T.cjs';
|
|
2
|
+
import { F as FetchFn } from '../shared-CucO_XsG.cjs';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* HashiCorp Vault provider (KVv1 + KVv2): reads one secret path into a flat map.
|
|
7
|
+
* Token comes from `auth.token` or `VAULT_TOKEN`; KVv2 envelopes unwrap only
|
|
8
|
+
* when a `metadata` sibling is present. Fail-closed on 403.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Options for {@link hashicorpProvider}. */
|
|
5
14
|
interface HashicorpOptions {
|
|
15
|
+
/** Vault base URL, e.g. `https://vault:8200`. */
|
|
6
16
|
url: string;
|
|
17
|
+
/** KV mount. Default `'secret'`. */
|
|
7
18
|
mount?: string;
|
|
19
|
+
/** Secret path: `data/app/prod` (KVv2) or `app/prod` (KVv1). */
|
|
8
20
|
path: string;
|
|
21
|
+
/** Explicit token. `''` means none (no `VAULT_TOKEN` fallback); unset reads `VAULT_TOKEN`. */
|
|
9
22
|
auth?: {
|
|
10
23
|
token?: string;
|
|
11
24
|
};
|
|
25
|
+
/** Pinned KVv2 version (`?version=`). */
|
|
12
26
|
version?: number | string;
|
|
27
|
+
/** Request timeout in ms. Default 5000. */
|
|
13
28
|
timeoutMs?: number;
|
|
29
|
+
/** Injectable fetch for tests. */
|
|
14
30
|
fetchFn?: FetchFn;
|
|
31
|
+
/** Response body cap in bytes. Default 1 MiB. */
|
|
15
32
|
maxBytes?: number;
|
|
16
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Reads one Vault path into a flat map. Concurrent `load()` calls share a
|
|
36
|
+
* single in-flight request; failures reset so the next call retries.
|
|
37
|
+
*/
|
|
17
38
|
declare function hashicorpProvider(opts: HashicorpOptions): SecretProvider;
|
|
18
39
|
|
|
19
40
|
export { type HashicorpOptions, hashicorpProvider };
|
|
@@ -1,19 +1,40 @@
|
|
|
1
|
-
import { a as SecretProvider } from '../types-
|
|
2
|
-
import { F as FetchFn } from '../shared-
|
|
1
|
+
import { a as SecretProvider } from '../types-B_Dc2L4T.js';
|
|
2
|
+
import { F as FetchFn } from '../shared-CucO_XsG.js';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* HashiCorp Vault provider (KVv1 + KVv2): reads one secret path into a flat map.
|
|
7
|
+
* Token comes from `auth.token` or `VAULT_TOKEN`; KVv2 envelopes unwrap only
|
|
8
|
+
* when a `metadata` sibling is present. Fail-closed on 403.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Options for {@link hashicorpProvider}. */
|
|
5
14
|
interface HashicorpOptions {
|
|
15
|
+
/** Vault base URL, e.g. `https://vault:8200`. */
|
|
6
16
|
url: string;
|
|
17
|
+
/** KV mount. Default `'secret'`. */
|
|
7
18
|
mount?: string;
|
|
19
|
+
/** Secret path: `data/app/prod` (KVv2) or `app/prod` (KVv1). */
|
|
8
20
|
path: string;
|
|
21
|
+
/** Explicit token. `''` means none (no `VAULT_TOKEN` fallback); unset reads `VAULT_TOKEN`. */
|
|
9
22
|
auth?: {
|
|
10
23
|
token?: string;
|
|
11
24
|
};
|
|
25
|
+
/** Pinned KVv2 version (`?version=`). */
|
|
12
26
|
version?: number | string;
|
|
27
|
+
/** Request timeout in ms. Default 5000. */
|
|
13
28
|
timeoutMs?: number;
|
|
29
|
+
/** Injectable fetch for tests. */
|
|
14
30
|
fetchFn?: FetchFn;
|
|
31
|
+
/** Response body cap in bytes. Default 1 MiB. */
|
|
15
32
|
maxBytes?: number;
|
|
16
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Reads one Vault path into a flat map. Concurrent `load()` calls share a
|
|
36
|
+
* single in-flight request; failures reset so the next call retries.
|
|
37
|
+
*/
|
|
17
38
|
declare function hashicorpProvider(opts: HashicorpOptions): SecretProvider;
|
|
18
39
|
|
|
19
40
|
export { type HashicorpOptions, hashicorpProvider };
|