@theholocron/env-utils 1.7.1 → 1.8.1

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
@@ -38,6 +38,14 @@ export const config = map((get) => ({
38
38
  }));
39
39
  ```
40
40
 
41
+ ### Logging
42
+
43
+ Debug output (key-loaded counts, missing-key warnings, deprecation notices) goes to `console.info`/`console.warn` by default. Pass an `EnvLogger` (any object shaped `{ info(message, meta?), warn(message, meta?) }`) to route it elsewhere:
44
+
45
+ ```typescript
46
+ const { get } = createEnvParser({ appName: "my-app", logger: myLogger });
47
+ ```
48
+
41
49
  ## Documentation
42
50
 
43
51
  Check out [The Holocron Archive](https://docs.theholocron.dev/projects/utils/) for more information.
package/dist/index.d.mts CHANGED
@@ -34,6 +34,17 @@ type EnvObject = {
34
34
  interface EnvLoader {
35
35
  load(): Record<string, string | undefined>;
36
36
  }
37
+ /**
38
+ * Minimal structural logger seam — accept any object shaped like this
39
+ * (including a real `@theholocron/observability` `Logger` via a thin
40
+ * adapter) without this package taking a dependency on it. Defaults to
41
+ * `console.info`/`console.warn` so behavior is unchanged when nothing
42
+ * is injected.
43
+ */
44
+ interface EnvLogger {
45
+ info(message: string, meta?: unknown): void;
46
+ warn(message: string, meta?: unknown): void;
47
+ }
37
48
  interface EnvParserOptions {
38
49
  /**
39
50
  * Display name for this app — used in debug output.
@@ -76,6 +87,11 @@ interface EnvParserOptions {
76
87
  * createEnvParser({ appName: "my-cli", namespaces: ["MY_TOOL"] })
77
88
  */
78
89
  namespaces?: string[];
90
+ /**
91
+ * Structured logger for debug output (key-loaded counts, missing-key
92
+ * warnings, deprecation notices). Defaults to `console.info`/`console.warn`.
93
+ */
94
+ logger?: EnvLogger;
79
95
  }
80
96
  interface EnvParser<T extends EnvObject = EnvObject> {
81
97
  /**
@@ -171,11 +187,11 @@ declare function normalizeEnvironment(value: string): Environment | undefined;
171
187
  /**
172
188
  * Resolve the current environment from input or process.env.
173
189
  */
174
- declare function getEnvironment(): Environment;
190
+ declare function getEnvironment(logger?: Pick<EnvLogger, "warn">): Environment;
175
191
  export declare const environment: {
176
192
  get: typeof getEnvironment;
177
193
  normalize: typeof normalizeEnvironment;
178
- isDeployed: () => boolean;
194
+ isDeployed: (logger?: Pick<EnvLogger, "warn">) => boolean;
179
195
  };
180
196
  type Environment = (typeof ENVIRONMENTS)[number];
181
197
  //#endregion
@@ -218,4 +234,4 @@ export declare function filterByNamespace(raw: Record<string, string | undefined
218
234
  */
219
235
  export declare function mergeNamespaces(raw: Record<string, string | undefined>, namespaces: string[]): Record<string, string | undefined>;
220
236
  //#endregion
221
- export type { EnvLoader, EnvLookup, EnvObject, EnvParser, EnvParserOptions, Environment, Primitive };
237
+ export type { EnvLoader, EnvLogger, EnvLookup, EnvObject, EnvParser, EnvParserOptions, Environment, Primitive };
package/dist/index.mjs CHANGED
@@ -48,14 +48,15 @@ function normalizeEnvironment(value) {
48
48
  production: "prod"
49
49
  })).get(value.toLowerCase());
50
50
  }
51
+ const consoleWarn = { warn: (message) => console.warn(message) };
51
52
  /**
52
53
  * Resolve the current environment from input or process.env.
53
54
  */
54
- function getEnvironment() {
55
+ function getEnvironment(logger = consoleWarn) {
55
56
  const raw = process.env["ENVIRONMENT"] || process.env["ENV"] || process.env["NODE_ENV"] || "prod";
56
57
  const normalized = normalizeEnvironment(String(raw));
57
58
  if (!normalized) {
58
- console.warn(`[@theholocron/utils-env] Unknown environment "${raw}", falling back to "${DEFAULT_ENVIRONMENT}"`);
59
+ logger.warn(`[@theholocron/utils-env] Unknown environment "${raw}", falling back to "${DEFAULT_ENVIRONMENT}"`);
59
60
  return DEFAULT_ENVIRONMENT;
60
61
  }
61
62
  return normalized;
@@ -63,7 +64,7 @@ function getEnvironment() {
63
64
  const environment = {
64
65
  get: getEnvironment,
65
66
  normalize: normalizeEnvironment,
66
- isDeployed: () => DEPLOYED_ENVIRONMENTS.has(getEnvironment())
67
+ isDeployed: (logger) => DEPLOYED_ENVIRONMENTS.has(getEnvironment(logger))
67
68
  };
68
69
  //#endregion
69
70
  //#region src/utils/coerce-value.ts
@@ -216,6 +217,10 @@ function normalizeKey(key) {
216
217
  }
217
218
  //#endregion
218
219
  //#region src/debug.ts
220
+ const consoleLogger = {
221
+ info: (message, meta) => meta === void 0 ? console.info(message) : console.info(message, meta),
222
+ warn: (message, meta) => meta === void 0 ? console.warn(message) : console.warn(message, meta)
223
+ };
219
224
  function isDebugEnabled() {
220
225
  const raw = process.env["DEBUG"];
221
226
  if (!raw) return false;
@@ -225,21 +230,21 @@ function isDebugEnabled() {
225
230
  "yes"
226
231
  ].includes(raw.toLowerCase());
227
232
  }
228
- function debugLog(appName, env) {
233
+ function debugLog(appName, env, logger = consoleLogger) {
229
234
  if (environment.isDeployed()) return;
230
235
  if (!isDebugEnabled()) return;
231
236
  const keys = collectKeys(env);
232
- console.info(`[@theholocron/utils-env] (debugLog) - ${appName} loaded ${keys.length} key(s) from environment`, { keys });
237
+ logger.info(`[@theholocron/utils-env] (debugLog) - ${appName} loaded ${keys.length} key(s) from environment`, { keys });
233
238
  }
234
- function warnMissingKey(appName, key) {
239
+ function warnMissingKey(appName, key, logger = consoleLogger) {
235
240
  if (environment.isDeployed()) return;
236
241
  if (!isDebugEnabled()) return;
237
- console.warn(`[@theholocron/utils-env] (warnMissingKey) - ${appName} key not found: "${key}" — returned undefined`);
242
+ logger.warn(`[@theholocron/utils-env] (warnMissingKey) - ${appName} key not found: "${key}" — returned undefined`);
238
243
  }
239
- function debugDeprecation(appName, oldKey, newKey, env) {
244
+ function debugDeprecation(appName, oldKey, newKey, env, logger = consoleLogger) {
240
245
  if (environment.isDeployed()) return;
241
246
  if (!(oldKey in env)) return;
242
- console.warn(`[@theholocron/utils-env] (debugDeprecation) - ${appName} "${oldKey}" is deprecated; migrate to "${newKey}"`);
247
+ logger.warn(`[@theholocron/utils-env] (debugDeprecation) - ${appName} "${oldKey}" is deprecated; migrate to "${newKey}"`);
243
248
  }
244
249
  const debug = {
245
250
  log: debugLog,
@@ -286,14 +291,14 @@ var DotenvLoader = class {
286
291
  * }));
287
292
  */
288
293
  function createEnvParser(options) {
289
- const { appName, loader = new DotenvLoader(), parseValues = true, namespaces } = options;
294
+ const { appName, loader = new DotenvLoader(), parseValues = true, namespaces, logger } = options;
290
295
  const loaded = loader.load();
291
296
  const env = buildEnvObject(namespaces && namespaces.length > 0 ? mergeNamespaces(loaded, namespaces) : loaded, parseValues);
292
- debug.log(appName, env);
297
+ debug.log(appName, env, logger);
293
298
  function get(key) {
294
299
  const path = normalizeKey(key);
295
300
  const value = getByPath(env, path);
296
- if (value === void 0) debug.warn(appName, key);
301
+ if (value === void 0) debug.warn(appName, key, logger);
297
302
  return value;
298
303
  }
299
304
  return {
@@ -305,7 +310,7 @@ function createEnvParser(options) {
305
310
  return fn(get);
306
311
  },
307
312
  deprecate(oldKey, newKey) {
308
- debug.deprecate(appName, oldKey, newKey, env);
313
+ debug.deprecate(appName, oldKey, newKey, env, logger);
309
314
  }
310
315
  };
311
316
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/env-utils",
3
- "version": "1.7.1",
3
+ "version": "1.8.1",
4
4
  "description": "Runtime environment detection and typed env-var parsing.",
5
5
  "keywords": [
6
6
  "env",
@@ -30,8 +30,8 @@
30
30
  "dist"
31
31
  ],
32
32
  "devDependencies": {
33
- "@theholocron/tsdown-config": "^7.33.0",
34
- "@theholocron/vitest-config": "^7.33.0",
33
+ "@theholocron/tsdown-config": "^8.2.0",
34
+ "@theholocron/vitest-config": "^8.2.0",
35
35
  "@tsconfig/node-lts": "^24.0.1",
36
36
  "@types/node": "^26.2.0",
37
37
  "@vitest/coverage-v8": "^4.1.10",