@theholocron/env-utils 1.1.2 → 1.2.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/dist/index.d.mts CHANGED
@@ -26,6 +26,33 @@ interface EnvParserOptions {
26
26
  * native types. Defaults to true.
27
27
  */
28
28
  parseValues?: boolean;
29
+ /**
30
+ * Namespace prefixes to filter and strip from raw env var keys.
31
+ * When set, only vars whose names start with one of these prefixes
32
+ * (case-insensitive, followed by `_`) are visible to the parser.
33
+ * The prefix is stripped before the key is normalised and looked up.
34
+ *
35
+ * Uses a **cascade model** — later entries win when the same key
36
+ * exists under multiple prefixes. Put broad/global namespaces first
37
+ * and project-specific overrides last (same mental model as CSS
38
+ * specificity or `Object.assign`).
39
+ *
40
+ * This lets you share an org-wide namespace (e.g. `HOLOCRON_` set
41
+ * once in `~/.bashrc`) as a base, then override individual vars with
42
+ * a project-specific prefix in `.env`, without copying every global
43
+ * var into each project.
44
+ *
45
+ * @example
46
+ * // HOLOCRON_DEBUG is the global default; CLI_TEMPLATE_DEBUG overrides it.
47
+ * createEnvParser({ appName: "my-cli", namespaces: ["HOLOCRON", "CLI_TEMPLATE"] })
48
+ *
49
+ * // Single namespace — only HOLOCRON_* vars are visible
50
+ * createEnvParser({ appName: "my-cli", namespaces: ["HOLOCRON"] })
51
+ *
52
+ * // Completely custom — no org namespace at all
53
+ * createEnvParser({ appName: "my-cli", namespaces: ["MY_TOOL"] })
54
+ */
55
+ namespaces?: string[];
29
56
  }
30
57
  interface EnvParser<T extends EnvObject = EnvObject> {
31
58
  /**
@@ -141,4 +168,31 @@ declare class DotenvLoader implements EnvLoader {
141
168
  load(): Record<string, string | undefined>;
142
169
  }
143
170
  //#endregion
144
- export { DEFAULT_ENVIRONMENT, DEPLOYED_ENVIRONMENTS, DotenvLoader, ENVIRONMENTS, type EnvLoader, type EnvObject, type EnvParser, type EnvParserOptions, type Environment, type Primitive, createEnvParser, environment };
171
+ //#region src/utils/filter-by-namespace.d.ts
172
+ /**
173
+ * Filter raw env vars to only those matching a namespace prefix,
174
+ * stripping the prefix from each key before returning.
175
+ *
176
+ * Case-insensitive: "holocron_debug" and "HOLOCRON_DEBUG" both match
177
+ * namespace "HOLOCRON".
178
+ *
179
+ * @example
180
+ * filterByNamespace({ HOLOCRON_DEBUG: "true", PORT: "3000" }, "HOLOCRON")
181
+ * // → { DEBUG: "true" }
182
+ */
183
+ declare function filterByNamespace(raw: Record<string, string | undefined>, namespace: string): Record<string, string | undefined>;
184
+ /**
185
+ * Merge multiple namespace-filtered views of a raw env record.
186
+ *
187
+ * Uses a cascade model — **later entries win** over earlier ones when
188
+ * the same key exists under multiple prefixes. Put broad/global
189
+ * namespaces first and project-specific overrides last, the same way
190
+ * you would layer CSS rules or Object.assign calls.
191
+ *
192
+ * @example
193
+ * // HOLOCRON_DEBUG is the org-wide default; CLI_TEMPLATE_DEBUG overrides it.
194
+ * mergeNamespaces(raw, ["HOLOCRON", "CLI_TEMPLATE"])
195
+ */
196
+ declare function mergeNamespaces(raw: Record<string, string | undefined>, namespaces: string[]): Record<string, string | undefined>;
197
+ //#endregion
198
+ export { DEFAULT_ENVIRONMENT, DEPLOYED_ENVIRONMENTS, DotenvLoader, ENVIRONMENTS, type EnvLoader, type EnvObject, type EnvParser, type EnvParserOptions, type Environment, type Primitive, createEnvParser, environment, filterByNamespace, mergeNamespaces };
package/dist/index.mjs CHANGED
@@ -119,6 +119,42 @@ function collectKeys(obj, prefix = "") {
119
119
  return keys;
120
120
  }
121
121
  //#endregion
122
+ //#region src/utils/filter-by-namespace.ts
123
+ /**
124
+ * Filter raw env vars to only those matching a namespace prefix,
125
+ * stripping the prefix from each key before returning.
126
+ *
127
+ * Case-insensitive: "holocron_debug" and "HOLOCRON_DEBUG" both match
128
+ * namespace "HOLOCRON".
129
+ *
130
+ * @example
131
+ * filterByNamespace({ HOLOCRON_DEBUG: "true", PORT: "3000" }, "HOLOCRON")
132
+ * // → { DEBUG: "true" }
133
+ */
134
+ function filterByNamespace(raw, namespace) {
135
+ const prefix = `${namespace.toUpperCase()}_`;
136
+ const result = {};
137
+ for (const [key, value] of Object.entries(raw)) if (key.toUpperCase().startsWith(prefix)) result[key.slice(prefix.length)] = value;
138
+ return result;
139
+ }
140
+ /**
141
+ * Merge multiple namespace-filtered views of a raw env record.
142
+ *
143
+ * Uses a cascade model — **later entries win** over earlier ones when
144
+ * the same key exists under multiple prefixes. Put broad/global
145
+ * namespaces first and project-specific overrides last, the same way
146
+ * you would layer CSS rules or Object.assign calls.
147
+ *
148
+ * @example
149
+ * // HOLOCRON_DEBUG is the org-wide default; CLI_TEMPLATE_DEBUG overrides it.
150
+ * mergeNamespaces(raw, ["HOLOCRON", "CLI_TEMPLATE"])
151
+ */
152
+ function mergeNamespaces(raw, namespaces) {
153
+ const result = {};
154
+ for (const ns of namespaces) Object.assign(result, filterByNamespace(raw, ns));
155
+ return result;
156
+ }
157
+ //#endregion
122
158
  //#region src/utils/get-by-path.ts
123
159
  /**
124
160
  * Traverse an EnvObject by a path array.
@@ -226,8 +262,9 @@ var DotenvLoader = class {
226
262
  * }));
227
263
  */
228
264
  function createEnvParser(options) {
229
- const { appName, loader = new DotenvLoader(), parseValues = true } = options;
230
- const env = buildEnvObject(loader.load(), parseValues);
265
+ const { appName, loader = new DotenvLoader(), parseValues = true, namespaces } = options;
266
+ const loaded = loader.load();
267
+ const env = buildEnvObject(namespaces && namespaces.length > 0 ? mergeNamespaces(loaded, namespaces) : loaded, parseValues);
231
268
  debug.log(appName, env);
232
269
  function get(key) {
233
270
  const path = normalizeKey(key);
@@ -249,4 +286,4 @@ function createEnvParser(options) {
249
286
  };
250
287
  }
251
288
  //#endregion
252
- export { DEFAULT_ENVIRONMENT, DEPLOYED_ENVIRONMENTS, DotenvLoader, ENVIRONMENTS, createEnvParser, environment };
289
+ export { DEFAULT_ENVIRONMENT, DEPLOYED_ENVIRONMENTS, DotenvLoader, ENVIRONMENTS, createEnvParser, environment, filterByNamespace, mergeNamespaces };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/env-utils",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "Runtime environment detection and typed env-var parsing.",
5
5
  "homepage": "https://github.com/theholocron/utils/tree/main/packages/env#readme",
6
6
  "bugs": "https://github.com/theholocron/utils/issues",
@@ -22,8 +22,8 @@
22
22
  "README.md"
23
23
  ],
24
24
  "devDependencies": {
25
- "@theholocron/tsdown-config": "^7.6.1",
26
- "@theholocron/vitest-config": "^7.6.1",
25
+ "@theholocron/tsdown-config": "^7.8.1",
26
+ "@theholocron/vitest-config": "^7.8.1",
27
27
  "@tsconfig/node-lts": "^24.0.0",
28
28
  "@types/node": "^26.1.2",
29
29
  "@vitest/coverage-v8": "^4.1.10",