@nifrajs/env 4.0.2 → 5.0.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/README.md CHANGED
@@ -64,7 +64,8 @@ pass the request's bindings: `defineEnv(shape, { source: env })`.
64
64
  ## Secret safety
65
65
 
66
66
  Error messages name the offending variable and the reason - **never its value** (it may be a
67
- secret). `defineEnv` returns a frozen object, so a validated config can't be mutated downstream.
67
+ secret). A BYO validator such as valibot may quote the value in its message; `defineEnv` replaces
68
+ it with `<redacted>`. `defineEnv` returns a frozen object, so a validated config can't be mutated downstream.
68
69
 
69
70
  ## For AI agents
70
71
 
package/dist/define.d.ts CHANGED
@@ -31,7 +31,8 @@ export interface DefineEnvOptions {
31
31
  * // ENV.PORT: number, ENV.NODE_ENV: "development" | "production" | "test", … all validated.
32
32
  * ```
33
33
  *
34
- * Errors name the offending variable and the reason - never its value (it may be a secret). BYO
34
+ * Errors name the offending variable and the reason - never its value (it may be a secret); a BYO
35
+ * validator's message that quotes the value gets `<redacted>` in its place. BYO
35
36
  * validators (`t`, zod, valibot) work too; only the `env.*` helpers coerce from strings, so a plain
36
37
  * `t.number()` would see the raw string - use `env.number()` for coercion.
37
38
  */
@@ -1 +1 @@
1
- {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEhE,kCAAkC;AAClC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AAEvD,4EAA4E;AAC5E,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,QAAQ,IAAI;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAA;AAE1F,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACrD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC,CA8BhG"}
1
+ {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEhE,kCAAkC;AAClC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AAEvD,4EAA4E;AAC5E,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,QAAQ,IAAI;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAA;AAE1F,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACrD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC,CAsChG"}
package/dist/define.js CHANGED
@@ -17,7 +17,8 @@
17
17
  * // ENV.PORT: number, ENV.NODE_ENV: "development" | "production" | "test", … all validated.
18
18
  * ```
19
19
  *
20
- * Errors name the offending variable and the reason - never its value (it may be a secret). BYO
20
+ * Errors name the offending variable and the reason - never its value (it may be a secret); a BYO
21
+ * validator's message that quotes the value gets `<redacted>` in its place. BYO
21
22
  * validators (`t`, zod, valibot) work too; only the `env.*` helpers coerce from strings, so a plain
22
23
  * `t.number()` would see the raw string - use `env.number()` for coercion.
23
24
  */
@@ -32,13 +33,20 @@ export function defineEnv(shape, options) {
32
33
  const result = schema["~standard"].validate(source[key]);
33
34
  if (result instanceof Promise) {
34
35
  // Env validation must be synchronous (it runs once, at import) - an async validator is a
35
- // configuration mistake, surfaced as a problem rather than an unhandled promise.
36
+ // configuration mistake, surfaced as a problem. Its promise is observed so a rejection is not
37
+ // reported as unhandled after the caller catches the refusal.
38
+ result.catch(() => { });
36
39
  problems.push(` ${key}: async validators are not supported in defineEnv`);
37
40
  continue;
38
41
  }
39
42
  if (result.issues !== undefined) {
40
- for (const i of result.issues)
41
- problems.push(` ${key}: ${i.message}`);
43
+ const raw = source[key];
44
+ // Only the `env.*` helpers promise value-free messages; valibot and hand-rolled validators
45
+ // quote the value, which may be a secret.
46
+ const foreign = schema["~standard"].vendor !== "nifra-env" && raw !== undefined && raw !== "";
47
+ for (const i of result.issues) {
48
+ problems.push(` ${key}: ${foreign ? i.message.replaceAll(raw, "<redacted>") : i.message}`);
49
+ }
42
50
  }
43
51
  else {
44
52
  out[key] = result.value;
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,SAAS,CAAqB,KAAQ,EAAE,OAA0B;IAChF,MAAM,MAAM,GACV,OAAO,EAAE,MAAM;QACd,UAAyE,CAAC,OAAO,EAAE,GAAG;QACvF,EAAE,CAAA;IACJ,MAAM,GAAG,GAA4B,EAAE,CAAA;IACvC,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAqB,CAAA;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QACxD,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC9B,yFAAyF;YACzF,iFAAiF;YACjF,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,mDAAmD,CAAC,CAAA;YAC1E,SAAQ;QACV,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM;gBAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;QACxE,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAA;QACzB,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,qCAAqC,QAAQ,CAAC,MAAM,iBAAiB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,4CAA4C,CACrI,CAAA;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAiB,CAAA;AAC3C,CAAC"}
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,SAAS,CAAqB,KAAQ,EAAE,OAA0B;IAChF,MAAM,MAAM,GACV,OAAO,EAAE,MAAM;QACd,UAAyE,CAAC,OAAO,EAAE,GAAG;QACvF,EAAE,CAAA;IACJ,MAAM,GAAG,GAA4B,EAAE,CAAA;IACvC,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAqB,CAAA;QAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QACxD,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC9B,yFAAyF;YACzF,8FAA8F;YAC9F,8DAA8D;YAC9D,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;YACtB,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,mDAAmD,CAAC,CAAA;YAC1E,SAAQ;QACV,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;YACvB,2FAA2F;YAC3F,0CAA0C;YAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,CAAA;YAC7F,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC9B,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;YAC7F,CAAC;QACH,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAA;QACzB,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,qCAAqC,QAAQ,CAAC,MAAM,iBAAiB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,4CAA4C,CACrI,CAAA;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAiB,CAAA;AAC3C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nifrajs/env",
3
- "version": "4.0.2",
3
+ "version": "5.0.0",
4
4
  "description": "Typed, validated environment variables for nifra - define a schema, get a frozen typed object, fail loud at boot listing every problem. Coercing helpers (number/port/boolean/url/enum) + any Standard Schema. Dependency-free, edge-safe.",
5
5
  "keywords": [
6
6
  "bun",
package/src/define.ts CHANGED
@@ -33,7 +33,8 @@ export interface DefineEnvOptions {
33
33
  * // ENV.PORT: number, ENV.NODE_ENV: "development" | "production" | "test", … all validated.
34
34
  * ```
35
35
  *
36
- * Errors name the offending variable and the reason - never its value (it may be a secret). BYO
36
+ * Errors name the offending variable and the reason - never its value (it may be a secret); a BYO
37
+ * validator's message that quotes the value gets `<redacted>` in its place. BYO
37
38
  * validators (`t`, zod, valibot) work too; only the `env.*` helpers coerce from strings, so a plain
38
39
  * `t.number()` would see the raw string - use `env.number()` for coercion.
39
40
  */
@@ -50,12 +51,20 @@ export function defineEnv<S extends EnvShape>(shape: S, options?: DefineEnvOptio
50
51
  const result = schema["~standard"].validate(source[key])
51
52
  if (result instanceof Promise) {
52
53
  // Env validation must be synchronous (it runs once, at import) - an async validator is a
53
- // configuration mistake, surfaced as a problem rather than an unhandled promise.
54
+ // configuration mistake, surfaced as a problem. Its promise is observed so a rejection is not
55
+ // reported as unhandled after the caller catches the refusal.
56
+ result.catch(() => {})
54
57
  problems.push(` ${key}: async validators are not supported in defineEnv`)
55
58
  continue
56
59
  }
57
60
  if (result.issues !== undefined) {
58
- for (const i of result.issues) problems.push(` ${key}: ${i.message}`)
61
+ const raw = source[key]
62
+ // Only the `env.*` helpers promise value-free messages; valibot and hand-rolled validators
63
+ // quote the value, which may be a secret.
64
+ const foreign = schema["~standard"].vendor !== "nifra-env" && raw !== undefined && raw !== ""
65
+ for (const i of result.issues) {
66
+ problems.push(` ${key}: ${foreign ? i.message.replaceAll(raw, "<redacted>") : i.message}`)
67
+ }
59
68
  } else {
60
69
  out[key] = result.value
61
70
  }