typed-settings 0.1.1 → 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/zod.d.cts +2 -0
- package/dist/adapters/zod.d.ts +2 -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.js +2 -2
- package/dist/framework/next.cjs +11 -6
- package/dist/framework/next.d.cts +3 -1
- package/dist/framework/next.d.ts +3 -1
- package/dist/framework/next.js +1 -1
- package/dist/framework/vite.cjs +11 -6
- package/dist/framework/vite.d.cts +3 -1
- package/dist/framework/vite.d.ts +3 -1
- package/dist/framework/vite.js +2 -2
- package/dist/index.cjs +11 -6
- package/dist/index.d.cts +10 -5
- package/dist/index.d.ts +10 -5
- package/dist/index.js +1 -1
- package/dist/node.cjs +11 -6
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +2 -2
- package/dist/{types-CClP1lxq.d.cts → types-B_Dc2L4T.d.cts} +4 -2
- package/dist/{types-CClP1lxq.d.ts → types-B_Dc2L4T.d.ts} +4 -2
- package/dist/vault/aws.d.cts +3 -1
- package/dist/vault/aws.d.ts +3 -1
- package/dist/vault/hashicorp.d.cts +3 -1
- package/dist/vault/hashicorp.d.ts +3 -1
- package/dist/vault/http.d.cts +3 -1
- package/dist/vault/http.d.ts +3 -1
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -185,7 +185,7 @@ Provider details: [docs/vault.md](docs/vault.md).
|
|
|
185
185
|
| `schema` | Standard Schema | required | zod / valibot / arktype object, or a legacy bridge. An async `validate()` forces `settingsAsync()` |
|
|
186
186
|
| `sources` | array | `['.env', 'env']` | layers in priority order, later wins |
|
|
187
187
|
| `prefix` | `string` | - | global prefix strip, case-insensitive, once |
|
|
188
|
-
| `envMap` | object |
|
|
188
|
+
| `envMap` | object | `{}` | maps an env key to the literal key it should occupy (used as-is: no strip/split) |
|
|
189
189
|
| `env` | object | `process.env` | the env snapshot. Pass `{}` to isolate, or a map in tests/on Edge |
|
|
190
190
|
| `expand` | `boolean` | `true` | `$VAR` expansion after merging. `false` leaves literals alone |
|
|
191
191
|
| `allowUnresolved` | `boolean` | `false` | `true` keeps `${MISSING}` as-is instead of throwing |
|
|
@@ -279,7 +279,9 @@ Things people actually hit, in rough order of frequency:
|
|
|
279
279
|
|
|
280
280
|
- **`USE_ASYNC: provider is async`.** One of your providers (or the schema itself) is async. Switch to `settingsAsync()`.
|
|
281
281
|
- **`E_UNRESOLVED: FOO missing`.** A `$FOO` reference points at nothing. Set the variable, give it a default (`${FOO:-fallback}`), or pass `allowUnresolved: true` to leave it literal.
|
|
282
|
-
- **Schema rejects everything.** Keys are lowercased during load, so schemas need lowercase keys
|
|
282
|
+
- **Schema rejects everything.** Keys are lowercased during load, so schemas need lowercase keys (`port`, not `PORT`). The failure mode is sneaky: `z.object({ PORT: z.coerce.number() })` never matches the lowercased input, so it validates `undefined`, and `z.coerce.number()` turns that into `NaN` — you get the confusing "expected number, received NaN".
|
|
283
|
+
- **Everything is silently empty or wrong.** Most often a global `prefix` ate your keys: matching applies to every source, so `prefix: 'APP_'` drops a YAML key like `port:` and a secrets-dir entry like `API_TOKEN` without a word. Scope it per source, or skip it and bridge env names via `envMap`.
|
|
284
|
+
- **Deno (JSR) refuses a fresh release.** Deno's minimum-dependency-age policy blocks versions published within ~24h. For local dev, run with `--minimum-dependency-age=0`.
|
|
283
285
|
- **`E_NO_FS` under ESM.** Core can't reach `node:fs` on its own. Import `typed-settings/node` once, or stick to `{ text }` / `{ map }` sources.
|
|
284
286
|
- **`E_UNKNOWN_KEY`.** Extra keys with `unknownKeys: 'reject'` (the CLI calls this `--strict`). Either drop the keys or switch to `strip` / `preserve`.
|
|
285
287
|
- **`SCHEMA_LOAD_ERROR`.** The CLI can't find your schema. Export it under the name `schema`, or point at it with `--schema-export NAME`.
|
package/dist/adapters/zod.d.cts
CHANGED
package/dist/adapters/zod.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { settings } from './chunk-
|
|
1
|
+
import { settings } from './chunk-YVJEZPPZ.js';
|
|
2
2
|
import { parseEnvText } from './chunk-F6DX3HXZ.js';
|
|
3
3
|
import { readFileSync, readdirSync, statSync, watch } from 'fs';
|
|
4
4
|
import { join, dirname, basename, resolve } from 'path';
|
|
@@ -253,12 +253,12 @@ function expandKeys(flat, opts) {
|
|
|
253
253
|
const stripped = stripPrefix(rawKey);
|
|
254
254
|
if (stripped === null) continue;
|
|
255
255
|
const useKey = stripped;
|
|
256
|
-
if (useKey.
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
if (FORBIDDEN.has(useKey.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
257
|
+
const parts = useKey.split("__");
|
|
258
|
+
const cleanSplit = parts.length > 1 && parts.every((p) => p !== "");
|
|
259
|
+
if (cleanSplit) {
|
|
259
260
|
for (const p of parts) {
|
|
260
261
|
if (FORBIDDEN.has(p.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
261
|
-
if (!p) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_EMPTY_SEGMENT" }], "E_EMPTY_SEGMENT");
|
|
262
262
|
}
|
|
263
263
|
const lowered = parts.map((p) => p.toLowerCase());
|
|
264
264
|
const top = lowered[0];
|
|
@@ -290,7 +290,6 @@ function expandKeys(flat, opts) {
|
|
|
290
290
|
setPath(out, lowered, value);
|
|
291
291
|
} else {
|
|
292
292
|
const k = useKey.toLowerCase();
|
|
293
|
-
if (FORBIDDEN.has(k)) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO" }], "E_PROTO");
|
|
294
293
|
const kind = kindOf(k);
|
|
295
294
|
if (kind.indexed) {
|
|
296
295
|
throw new ConfigError(
|
|
@@ -791,7 +790,13 @@ function makeLookup(merged, envSnapshot) {
|
|
|
791
790
|
function expandDeepStrings(obj, lookup, ctx, path = []) {
|
|
792
791
|
if (typeof obj === "string") {
|
|
793
792
|
const top = (path[0] ?? "<root>").toLowerCase();
|
|
794
|
-
|
|
793
|
+
const from = ctx.fromMap.get(top) ?? "config";
|
|
794
|
+
try {
|
|
795
|
+
return expandLeaf(obj, lookup, { ...ctx, from }, path.map((p) => p.toLowerCase()));
|
|
796
|
+
} catch (e) {
|
|
797
|
+
if (from === "env") return obj;
|
|
798
|
+
throw e;
|
|
799
|
+
}
|
|
795
800
|
}
|
|
796
801
|
if (Array.isArray(obj)) return obj.map((x, i) => expandDeepStrings(x, lookup, ctx, [...path, String(i)]));
|
|
797
802
|
if (obj && typeof obj === "object") {
|
package/dist/cli/main.cjs
CHANGED
|
@@ -485,12 +485,12 @@ function expandKeys(flat, opts) {
|
|
|
485
485
|
const stripped = stripPrefix(rawKey);
|
|
486
486
|
if (stripped === null) continue;
|
|
487
487
|
const useKey = stripped;
|
|
488
|
-
if (useKey.
|
|
489
|
-
|
|
490
|
-
|
|
488
|
+
if (FORBIDDEN.has(useKey.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
489
|
+
const parts = useKey.split("__");
|
|
490
|
+
const cleanSplit = parts.length > 1 && parts.every((p) => p !== "");
|
|
491
|
+
if (cleanSplit) {
|
|
491
492
|
for (const p of parts) {
|
|
492
493
|
if (FORBIDDEN.has(p.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
493
|
-
if (!p) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_EMPTY_SEGMENT" }], "E_EMPTY_SEGMENT");
|
|
494
494
|
}
|
|
495
495
|
const lowered = parts.map((p) => p.toLowerCase());
|
|
496
496
|
const top = lowered[0];
|
|
@@ -522,7 +522,6 @@ function expandKeys(flat, opts) {
|
|
|
522
522
|
setPath(out, lowered, value);
|
|
523
523
|
} else {
|
|
524
524
|
const k = useKey.toLowerCase();
|
|
525
|
-
if (FORBIDDEN.has(k)) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO" }], "E_PROTO");
|
|
526
525
|
const kind = kindOf(k);
|
|
527
526
|
if (kind.indexed) {
|
|
528
527
|
throw new ConfigError(
|
|
@@ -1044,7 +1043,13 @@ function makeLookup(merged, envSnapshot) {
|
|
|
1044
1043
|
function expandDeepStrings(obj, lookup, ctx, path = []) {
|
|
1045
1044
|
if (typeof obj === "string") {
|
|
1046
1045
|
const top = (path[0] ?? "<root>").toLowerCase();
|
|
1047
|
-
|
|
1046
|
+
const from = ctx.fromMap.get(top) ?? "config";
|
|
1047
|
+
try {
|
|
1048
|
+
return expandLeaf(obj, lookup, { ...ctx, from }, path.map((p) => p.toLowerCase()));
|
|
1049
|
+
} catch (e) {
|
|
1050
|
+
if (from === "env") return obj;
|
|
1051
|
+
throw e;
|
|
1052
|
+
}
|
|
1048
1053
|
}
|
|
1049
1054
|
if (Array.isArray(obj)) return obj.map((x, i) => expandDeepStrings(x, lookup, ctx, [...path, String(i)]));
|
|
1050
1055
|
if (obj && typeof obj === "object") {
|
package/dist/cli/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { watchSettings } from '../chunk-
|
|
3
|
-
import { settings } from '../chunk-
|
|
2
|
+
import { watchSettings } from '../chunk-DEP5SD4J.js';
|
|
3
|
+
import { settings } from '../chunk-YVJEZPPZ.js';
|
|
4
4
|
import '../chunk-33M5GIKQ.js';
|
|
5
5
|
import '../chunk-OVFMKC2O.js';
|
|
6
6
|
import '../chunk-UFUHHR2J.js';
|
package/dist/framework/next.cjs
CHANGED
|
@@ -440,12 +440,12 @@ function expandKeys(flat, opts) {
|
|
|
440
440
|
const stripped = stripPrefix(rawKey);
|
|
441
441
|
if (stripped === null) continue;
|
|
442
442
|
const useKey = stripped;
|
|
443
|
-
if (useKey.
|
|
444
|
-
|
|
445
|
-
|
|
443
|
+
if (FORBIDDEN.has(useKey.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
444
|
+
const parts = useKey.split("__");
|
|
445
|
+
const cleanSplit = parts.length > 1 && parts.every((p) => p !== "");
|
|
446
|
+
if (cleanSplit) {
|
|
446
447
|
for (const p of parts) {
|
|
447
448
|
if (FORBIDDEN.has(p.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
448
|
-
if (!p) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_EMPTY_SEGMENT" }], "E_EMPTY_SEGMENT");
|
|
449
449
|
}
|
|
450
450
|
const lowered = parts.map((p) => p.toLowerCase());
|
|
451
451
|
const top = lowered[0];
|
|
@@ -477,7 +477,6 @@ function expandKeys(flat, opts) {
|
|
|
477
477
|
setPath(out, lowered, value);
|
|
478
478
|
} else {
|
|
479
479
|
const k = useKey.toLowerCase();
|
|
480
|
-
if (FORBIDDEN.has(k)) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO" }], "E_PROTO");
|
|
481
480
|
const kind = kindOf(k);
|
|
482
481
|
if (kind.indexed) {
|
|
483
482
|
throw new ConfigError(
|
|
@@ -949,7 +948,13 @@ function makeLookup(merged, envSnapshot) {
|
|
|
949
948
|
function expandDeepStrings(obj, lookup, ctx, path = []) {
|
|
950
949
|
if (typeof obj === "string") {
|
|
951
950
|
const top = (path[0] ?? "<root>").toLowerCase();
|
|
952
|
-
|
|
951
|
+
const from = ctx.fromMap.get(top) ?? "config";
|
|
952
|
+
try {
|
|
953
|
+
return expandLeaf(obj, lookup, { ...ctx, from }, path.map((p) => p.toLowerCase()));
|
|
954
|
+
} catch (e) {
|
|
955
|
+
if (from === "env") return obj;
|
|
956
|
+
throw e;
|
|
957
|
+
}
|
|
953
958
|
}
|
|
954
959
|
if (Array.isArray(obj)) return obj.map((x, i) => expandDeepStrings(x, lookup, ctx, [...path, String(i)]));
|
|
955
960
|
if (obj && typeof obj === "object") {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
2
|
export { pickPublic, settings, settingsAsync } from '../index.cjs';
|
|
3
|
-
export { S as SettingsOptions } from '../types-
|
|
3
|
+
export { S as SettingsOptions } from '../types-B_Dc2L4T.cjs';
|
|
4
4
|
export { C as ConfigError } from '../errors-itGaU4Q8.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -12,6 +12,8 @@ export { C as ConfigError } from '../errors-itGaU4Q8.cjs';
|
|
|
12
12
|
* outside a React Server Component, which would break plain Node/vitest usage).
|
|
13
13
|
* // settings.ts (server)
|
|
14
14
|
* import 'server-only';
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
15
17
|
*/
|
|
16
18
|
|
|
17
19
|
/** Explicit public subset - no spread, keys enumerated so secrets can't leak via `...cfg`. */
|
package/dist/framework/next.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
2
|
export { pickPublic, settings, settingsAsync } from '../index.js';
|
|
3
|
-
export { S as SettingsOptions } from '../types-
|
|
3
|
+
export { S as SettingsOptions } from '../types-B_Dc2L4T.js';
|
|
4
4
|
export { C as ConfigError } from '../errors-itGaU4Q8.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -12,6 +12,8 @@ export { C as ConfigError } from '../errors-itGaU4Q8.js';
|
|
|
12
12
|
* outside a React Server Component, which would break plain Node/vitest usage).
|
|
13
13
|
* // settings.ts (server)
|
|
14
14
|
* import 'server-only';
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
15
17
|
*/
|
|
16
18
|
|
|
17
19
|
/** Explicit public subset - no spread, keys enumerated so secrets can't leak via `...cfg`. */
|
package/dist/framework/next.js
CHANGED
package/dist/framework/vite.cjs
CHANGED
|
@@ -440,12 +440,12 @@ function expandKeys(flat, opts) {
|
|
|
440
440
|
const stripped = stripPrefix(rawKey);
|
|
441
441
|
if (stripped === null) continue;
|
|
442
442
|
const useKey = stripped;
|
|
443
|
-
if (useKey.
|
|
444
|
-
|
|
445
|
-
|
|
443
|
+
if (FORBIDDEN.has(useKey.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
444
|
+
const parts = useKey.split("__");
|
|
445
|
+
const cleanSplit = parts.length > 1 && parts.every((p) => p !== "");
|
|
446
|
+
if (cleanSplit) {
|
|
446
447
|
for (const p of parts) {
|
|
447
448
|
if (FORBIDDEN.has(p.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
448
|
-
if (!p) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_EMPTY_SEGMENT" }], "E_EMPTY_SEGMENT");
|
|
449
449
|
}
|
|
450
450
|
const lowered = parts.map((p) => p.toLowerCase());
|
|
451
451
|
const top = lowered[0];
|
|
@@ -477,7 +477,6 @@ function expandKeys(flat, opts) {
|
|
|
477
477
|
setPath(out, lowered, value);
|
|
478
478
|
} else {
|
|
479
479
|
const k = useKey.toLowerCase();
|
|
480
|
-
if (FORBIDDEN.has(k)) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO" }], "E_PROTO");
|
|
481
480
|
const kind = kindOf(k);
|
|
482
481
|
if (kind.indexed) {
|
|
483
482
|
throw new ConfigError(
|
|
@@ -949,7 +948,13 @@ function makeLookup(merged, envSnapshot) {
|
|
|
949
948
|
function expandDeepStrings(obj, lookup, ctx, path = []) {
|
|
950
949
|
if (typeof obj === "string") {
|
|
951
950
|
const top = (path[0] ?? "<root>").toLowerCase();
|
|
952
|
-
|
|
951
|
+
const from = ctx.fromMap.get(top) ?? "config";
|
|
952
|
+
try {
|
|
953
|
+
return expandLeaf(obj, lookup, { ...ctx, from }, path.map((p) => p.toLowerCase()));
|
|
954
|
+
} catch (e) {
|
|
955
|
+
if (from === "env") return obj;
|
|
956
|
+
throw e;
|
|
957
|
+
}
|
|
953
958
|
}
|
|
954
959
|
if (Array.isArray(obj)) return obj.map((x, i) => expandDeepStrings(x, lookup, ctx, [...path, String(i)]));
|
|
955
960
|
if (obj && typeof obj === "object") {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
2
|
export { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
3
|
export { pickPublic, settings, settingsAsync } from '../index.cjs';
|
|
4
|
-
import { S as SettingsOptions, F as Flat } from '../types-
|
|
4
|
+
import { S as SettingsOptions, F as Flat } from '../types-B_Dc2L4T.cjs';
|
|
5
5
|
export { C as ConfigError } from '../errors-itGaU4Q8.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -10,6 +10,8 @@ export { C as ConfigError } from '../errors-itGaU4Q8.cjs';
|
|
|
10
10
|
* Rules: never spread `import.meta.env` (it drags server secrets into the
|
|
11
11
|
* client bundle). Pass it as a map; file preloading belongs in `vite.config.ts`
|
|
12
12
|
* via `loadEnvFiles()` passed as `{ text }`.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
17
|
/**
|
package/dist/framework/vite.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
2
|
export { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
3
|
export { pickPublic, settings, settingsAsync } from '../index.js';
|
|
4
|
-
import { S as SettingsOptions, F as Flat } from '../types-
|
|
4
|
+
import { S as SettingsOptions, F as Flat } from '../types-B_Dc2L4T.js';
|
|
5
5
|
export { C as ConfigError } from '../errors-itGaU4Q8.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -10,6 +10,8 @@ export { C as ConfigError } from '../errors-itGaU4Q8.js';
|
|
|
10
10
|
* Rules: never spread `import.meta.env` (it drags server secrets into the
|
|
11
11
|
* client bundle). Pass it as a map; file preloading belongs in `vite.config.ts`
|
|
12
12
|
* via `loadEnvFiles()` passed as `{ text }`.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
17
|
/**
|
package/dist/framework/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { settings } from '../chunk-
|
|
2
|
-
export { pickPublic, settings, settingsAsync } from '../chunk-
|
|
1
|
+
import { settings } from '../chunk-YVJEZPPZ.js';
|
|
2
|
+
export { pickPublic, settings, settingsAsync } from '../chunk-YVJEZPPZ.js';
|
|
3
3
|
import '../chunk-33M5GIKQ.js';
|
|
4
4
|
import '../chunk-OVFMKC2O.js';
|
|
5
5
|
import '../chunk-UFUHHR2J.js';
|
package/dist/index.cjs
CHANGED
|
@@ -440,12 +440,12 @@ function expandKeys(flat, opts) {
|
|
|
440
440
|
const stripped = stripPrefix(rawKey);
|
|
441
441
|
if (stripped === null) continue;
|
|
442
442
|
const useKey = stripped;
|
|
443
|
-
if (useKey.
|
|
444
|
-
|
|
445
|
-
|
|
443
|
+
if (FORBIDDEN.has(useKey.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
444
|
+
const parts = useKey.split("__");
|
|
445
|
+
const cleanSplit = parts.length > 1 && parts.every((p) => p !== "");
|
|
446
|
+
if (cleanSplit) {
|
|
446
447
|
for (const p of parts) {
|
|
447
448
|
if (FORBIDDEN.has(p.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
|
|
448
|
-
if (!p) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_EMPTY_SEGMENT" }], "E_EMPTY_SEGMENT");
|
|
449
449
|
}
|
|
450
450
|
const lowered = parts.map((p) => p.toLowerCase());
|
|
451
451
|
const top = lowered[0];
|
|
@@ -477,7 +477,6 @@ function expandKeys(flat, opts) {
|
|
|
477
477
|
setPath(out, lowered, value);
|
|
478
478
|
} else {
|
|
479
479
|
const k = useKey.toLowerCase();
|
|
480
|
-
if (FORBIDDEN.has(k)) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO" }], "E_PROTO");
|
|
481
480
|
const kind = kindOf(k);
|
|
482
481
|
if (kind.indexed) {
|
|
483
482
|
throw new ConfigError(
|
|
@@ -978,7 +977,13 @@ function makeLookup(merged, envSnapshot) {
|
|
|
978
977
|
function expandDeepStrings(obj, lookup, ctx, path = []) {
|
|
979
978
|
if (typeof obj === "string") {
|
|
980
979
|
const top = (path[0] ?? "<root>").toLowerCase();
|
|
981
|
-
|
|
980
|
+
const from = ctx.fromMap.get(top) ?? "config";
|
|
981
|
+
try {
|
|
982
|
+
return expandLeaf(obj, lookup, { ...ctx, from }, path.map((p) => p.toLowerCase()));
|
|
983
|
+
} catch (e) {
|
|
984
|
+
if (from === "env") return obj;
|
|
985
|
+
throw e;
|
|
986
|
+
}
|
|
982
987
|
}
|
|
983
988
|
if (Array.isArray(obj)) return obj.map((x, i) => expandDeepStrings(x, lookup, ctx, [...path, String(i)]));
|
|
984
989
|
if (obj && typeof obj === "object") {
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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-
|
|
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
4
|
export { C as ConfigError } from './errors-itGaU4Q8.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -10,6 +10,8 @@ export { C as ConfigError } from './errors-itGaU4Q8.cjs';
|
|
|
10
10
|
* secrets-dir maps, and vault secrets, then merge, expand `$VAR` references,
|
|
11
11
|
* coerce, validate against a Standard Schema, and return the result frozen.
|
|
12
12
|
* Anything invalid throws `ConfigError` at boot with the key and source attached.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
17
|
/**
|
|
@@ -31,9 +33,12 @@ declare function pickPublic<T extends object>(cfg: T, keys: (keyof T)[]): Partia
|
|
|
31
33
|
declare function viteSettings<S extends StandardSchemaV1>(opts: SettingsOptions<S>, metaEnv: Flat): StandardSchemaV1.InferOutput<S>;
|
|
32
34
|
/**
|
|
33
35
|
* Loads, merges, expands, coerces, and validates config synchronously, returning
|
|
34
|
-
* the inferred output type, frozen.
|
|
35
|
-
*
|
|
36
|
-
*
|
|
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()`.
|
|
37
42
|
*/
|
|
38
43
|
declare function settings<S extends StandardSchemaV1>(opts: SettingsOptions<S>): StandardSchemaV1.InferOutput<S>;
|
|
39
44
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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-
|
|
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
4
|
export { C as ConfigError } from './errors-itGaU4Q8.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -10,6 +10,8 @@ export { C as ConfigError } from './errors-itGaU4Q8.js';
|
|
|
10
10
|
* secrets-dir maps, and vault secrets, then merge, expand `$VAR` references,
|
|
11
11
|
* coerce, validate against a Standard Schema, and return the result frozen.
|
|
12
12
|
* Anything invalid throws `ConfigError` at boot with the key and source attached.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
17
|
/**
|
|
@@ -31,9 +33,12 @@ declare function pickPublic<T extends object>(cfg: T, keys: (keyof T)[]): Partia
|
|
|
31
33
|
declare function viteSettings<S extends StandardSchemaV1>(opts: SettingsOptions<S>, metaEnv: Flat): StandardSchemaV1.InferOutput<S>;
|
|
32
34
|
/**
|
|
33
35
|
* Loads, merges, expands, coerces, and validates config synchronously, returning
|
|
34
|
-
* the inferred output type, frozen.
|
|
35
|
-
*
|
|
36
|
-
*
|
|
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()`.
|
|
37
42
|
*/
|
|
38
43
|
declare function settings<S extends StandardSchemaV1>(opts: SettingsOptions<S>): StandardSchemaV1.InferOutput<S>;
|
|
39
44
|
/**
|
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
package/dist/node.d.ts
CHANGED
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';
|
|
@@ -10,8 +10,10 @@ interface SecretProvider {
|
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* One config source. Strings `'env' | '.env' | '.env.local'` are built-ins,
|
|
13
|
-
* any other string is a file path
|
|
14
|
-
*
|
|
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.
|
|
15
17
|
*/
|
|
16
18
|
type SourceInput = 'env' | '.env' | '.env.local' | {
|
|
17
19
|
text: string;
|
|
@@ -10,8 +10,10 @@ interface SecretProvider {
|
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* One config source. Strings `'env' | '.env' | '.env.local'` are built-ins,
|
|
13
|
-
* any other string is a file path
|
|
14
|
-
*
|
|
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.
|
|
15
17
|
*/
|
|
16
18
|
type SourceInput = 'env' | '.env' | '.env.local' | {
|
|
17
19
|
text: string;
|
package/dist/vault/aws.d.cts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
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
4
|
/**
|
|
5
5
|
* AWS provider: Secrets Manager ids plus SSM parameters (with decryption)
|
|
6
6
|
* merged into one flat map. SDK clients are injected, never imported blindly,
|
|
7
7
|
* so tests can pass fakes and Edge bundles stay lean.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
/** Minimal Secrets Manager surface this provider needs (real SDK client or a fake). */
|
package/dist/vault/aws.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
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
4
|
/**
|
|
5
5
|
* AWS provider: Secrets Manager ids plus SSM parameters (with decryption)
|
|
6
6
|
* merged into one flat map. SDK clients are injected, never imported blindly,
|
|
7
7
|
* so tests can pass fakes and Edge bundles stay lean.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
/** Minimal Secrets Manager surface this provider needs (real SDK client or a fake). */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as SecretProvider } from '../types-
|
|
1
|
+
import { a as SecretProvider } from '../types-B_Dc2L4T.cjs';
|
|
2
2
|
import { F as FetchFn } from '../shared-CucO_XsG.cjs';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
@@ -6,6 +6,8 @@ import '@standard-schema/spec';
|
|
|
6
6
|
* HashiCorp Vault provider (KVv1 + KVv2): reads one secret path into a flat map.
|
|
7
7
|
* Token comes from `auth.token` or `VAULT_TOKEN`; KVv2 envelopes unwrap only
|
|
8
8
|
* when a `metadata` sibling is present. Fail-closed on 403.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
/** Options for {@link hashicorpProvider}. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as SecretProvider } from '../types-
|
|
1
|
+
import { a as SecretProvider } from '../types-B_Dc2L4T.js';
|
|
2
2
|
import { F as FetchFn } from '../shared-CucO_XsG.js';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
@@ -6,6 +6,8 @@ import '@standard-schema/spec';
|
|
|
6
6
|
* HashiCorp Vault provider (KVv1 + KVv2): reads one secret path into a flat map.
|
|
7
7
|
* Token comes from `auth.token` or `VAULT_TOKEN`; KVv2 envelopes unwrap only
|
|
8
8
|
* when a `metadata` sibling is present. Fail-closed on 403.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
/** Options for {@link hashicorpProvider}. */
|
package/dist/vault/http.d.cts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { F as Flat, a as SecretProvider } from '../types-
|
|
1
|
+
import { F as Flat, a as SecretProvider } from '../types-B_Dc2L4T.cjs';
|
|
2
2
|
import { F as FetchFn } from '../shared-CucO_XsG.cjs';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Generic HTTP secret provider: GETs a JSON endpoint and reads a dot-path
|
|
7
7
|
* (`jsonPath`, default `'data'`) into a flat map. Auth rides in `headers`.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
/** Options for {@link httpProvider}. */
|
package/dist/vault/http.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { F as Flat, a as SecretProvider } from '../types-
|
|
1
|
+
import { F as Flat, a as SecretProvider } from '../types-B_Dc2L4T.js';
|
|
2
2
|
import { F as FetchFn } from '../shared-CucO_XsG.js';
|
|
3
3
|
import '@standard-schema/spec';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Generic HTTP secret provider: GETs a JSON endpoint and reads a dot-path
|
|
7
7
|
* (`jsonPath`, default `'data'`) into a flat map. Auth rides in `headers`.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
/** Options for {@link httpProvider}. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typed-settings",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "One-call typed config for TS: env + .env + yaml/toml/json + secrets-dir + vault -> frozen object. Standard Schema + legacy bridges.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -89,6 +89,14 @@
|
|
|
89
89
|
"standard-schema"
|
|
90
90
|
],
|
|
91
91
|
"license": "MIT",
|
|
92
|
+
"repository": {
|
|
93
|
+
"type": "git",
|
|
94
|
+
"url": "https://github.com/prosubodh/typed-settings"
|
|
95
|
+
},
|
|
96
|
+
"homepage": "https://github.com/prosubodh/typed-settings#readme",
|
|
97
|
+
"bugs": {
|
|
98
|
+
"url": "https://github.com/prosubodh/typed-settings/issues"
|
|
99
|
+
},
|
|
92
100
|
"engines": {
|
|
93
101
|
"node": ">=20"
|
|
94
102
|
},
|