@sourceregistry/node-env 1.0.0 → 1.1.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
@@ -13,7 +13,7 @@ No dependencies, focus on runtime safety.
13
13
  Key features:
14
14
  - Load `.env` file (ignores comments, blank lines, quotes) and merge into `process.env`.
15
15
  - Access variables via `.string()`, `.number()`, `.boolean()` with defaults.
16
- - Check keys with `.has()`, `.defined()`.
16
+ - Check keys with `.has()`, `.defined()`, `.assert()`.
17
17
  - Get `env.dev` boolean for “development vs production” mode.
18
18
  - Collect variables with a common prefix via `.collection()`, optional prefix removal & reviver.
19
19
  - Utility method `.utils.select()` for feature‐flag style branching.
@@ -84,7 +84,7 @@ When you have many environment variables prefixed in a group:
84
84
 
85
85
  ```ts
86
86
  // .env
87
- API_URL=https://api.example.com
87
+ API_URL="https://api.example.com"
88
88
  API_KEY=abcdef
89
89
  API_TIMEOUT=5000
90
90
 
@@ -120,11 +120,12 @@ const mode = env.utils.select("FEATURE_X", "enabled", "disabled");
120
120
  ## API Reference
121
121
 
122
122
  | Method | Description |
123
- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
123
+ |--------------------------------------------------|-----------------------------------------------------------------------------------------------------|
124
124
  | `env.string(key, default?)` | Return the variable as a string (or default). |
125
125
  | `env.number(key, default?)` | Parse variable to number (or default). |
126
126
  | `env.boolean(key, default?)` | Parse variable to boolean (or default). |
127
127
  | `env.has(key)` | Returns true if key exists in `process.env`. |
128
+ | `env.assert([keys], error_builder?)` | Throws an error if one or more keys doesn't exists in `process.env`. |
128
129
  | `env.defined(key)` | Returns true if key exists and value is not `undefined`. |
129
130
  | `env.dev` | Boolean flag: true if `NODE_ENV !== "production"`. |
130
131
  | `env.collection(prefix, options?)` | Get an object of all env keys starting with `prefix`. Options include `removePrefix` and `reviver`. |
package/dist/index.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("fs");function v(e=".env"){if(!i.existsSync(e))return{};try{const r=i.readFileSync(e,"utf8");return Object.fromEntries(r.split(/\r?\n/).filter(t=>t&&!t.trim().startsWith("#")&&t.includes("=")).map(t=>{const[s,...n]=t.split("=");let o=n.join("=").trim();return(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),[s.trim(),o]}))}catch(r){const t=r?.message??"Failed to load .env";return globalThis.logger?.warn?globalThis.logger.warn(t):console.warn(t),{}}}const a=v();for(const[e,r]of Object.entries(a))e in process.env||(process.env[e]=r);const c=Object.freeze({string(e,r){return e in process.env||(process.env[e]=r??""),process.env[e]},number(e,r=0){const t=process.env[e];if(t===void 0)return process.env[e]=String(r),r;const s=Number(t);return Number.isFinite(s)?s:r},boolean(e,r=!1){const t=process.env[e];if(t===void 0)return process.env[e]=r?"true":"false",r;const s=t.toLowerCase();return s==="true"||s==="1"},has(e){return Object.prototype.hasOwnProperty.call(process.env,e)},defined(e){return c.has(e)&&process.env[e]!==void 0},get dev(){return process.env.NODE_ENV!=="production"},collection(e,r={}){const{reviver:t=n=>n,removePrefix:s=!1}=r;return Object.fromEntries(Object.entries(process.env).filter(([n])=>n.startsWith(e)).map(([n,o])=>[s?n.replace(e,""):n,t(o,n)]))},utils:Object.freeze({select(e,r,t,s=n=>c.boolean(n)){return s(e,process.env[e])?r:t}}),get raw(){return Object.freeze(a)}});exports.env=c;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("fs");function l(e=".env"){if(!c.existsSync(e))return{};try{const t=c.readFileSync(e,"utf8");return Object.fromEntries(t.split(/\r?\n/).filter(r=>r&&!r.trim().startsWith("#")&&r.includes("=")).map(r=>{const[s,...n]=r.split("=");let o=n.join("=").trim();return(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),[s.trim(),o]}))}catch(t){const r=t?.message??"Failed to load .env";return globalThis.logger?.warn?globalThis.logger.warn(r):console.warn(r),{}}}const a=l();for(const[e,t]of Object.entries(a))e in process.env||(process.env[e]=t);const i=Object.freeze({string(e,t){return e in process.env||(process.env[e]=t??""),process.env[e]},number(e,t=0){const r=process.env[e];if(r===void 0)return process.env[e]=String(t),t;const s=Number(r);return Number.isFinite(s)?s:t},boolean(e,t=!1){const r=process.env[e];if(r===void 0)return process.env[e]=t?"true":"false",t;const s=r.toLowerCase();return s==="true"||s==="1"},has(e){return Object.prototype.hasOwnProperty.call(process.env,e)},assert(e,t=(r=>new Error(`Missing required keys(${r.join()}) in environment`))){const r=[];if(e.forEach(s=>this.has(s)?void 0:r.push(s)),r.length>0){const s=t(r);throw typeof s=="string"?new Error(s):s}},defined(e){return i.has(e)&&process.env[e]!==void 0},get dev(){return process.env.NODE_ENV!=="production"},collection(e,t={}){const{reviver:r=n=>n,removePrefix:s=!1}=t;return Object.fromEntries(Object.entries(process.env).filter(([n])=>n.startsWith(e)).map(([n,o])=>[s?n.replace(e,""):n,r(o,n)]))},utils:Object.freeze({select(e,t,r,s=n=>i.boolean(n)){return s(e,process.env[e])?t:r}}),get raw(){return Object.freeze(a)}});exports.env=i;
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/index.ts"],"sourcesContent":["import { readFileSync, existsSync } from \"fs\";\n\nfunction loadDotEnv(file = \".env\") {\n if (!existsSync(file)) return {};\n\n try {\n const text = readFileSync(file, \"utf8\");\n return Object.fromEntries(\n text\n .split(/\\r?\\n/)\n .filter((line) => line && !line.trim().startsWith(\"#\") && line.includes(\"=\"))\n .map((line) => {\n const [key, ...rest] = line.split(\"=\");\n let value = rest.join(\"=\").trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n return [key.trim(), value];\n })\n );\n } catch (e: any) {\n const msg = e?.message ?? \"Failed to load .env\";\n // @ts-ignore\n if (globalThis.logger?.warn) globalThis.logger.warn(msg);\n else console.warn(msg);\n return {};\n }\n}\n\n// merge .env into process.env at load\nconst dotEnvVars = loadDotEnv();\nfor (const [k, v] of Object.entries(dotEnvVars)) {\n if (!(k in process.env)) process.env[k] = v;\n}\n\nexport const env = Object.freeze({\n string<T extends string = string>(key: Uppercase<string>, _default?: T): T {\n if (!(key in process.env)) process.env[key] = _default ?? \"\";\n return process.env[key] as T;\n },\n\n number(key: Uppercase<string>, _default = 0): number {\n const raw = process.env[key];\n if (raw === undefined) {\n process.env[key] = String(_default);\n return _default;\n }\n const val = Number(raw);\n return Number.isFinite(val) ? val : _default;\n },\n\n boolean(key: Uppercase<string>, _default = false): boolean {\n const raw = process.env[key];\n if (raw === undefined) {\n process.env[key] = _default ? \"true\" : \"false\";\n return _default;\n }\n const val = raw.toLowerCase();\n return val === \"true\" || val === \"1\";\n },\n\n has(key: Uppercase<string>): boolean {\n return Object.prototype.hasOwnProperty.call(process.env, key);\n },\n\n defined(key: Uppercase<string>): boolean {\n return env.has(key) && process.env[key] !== undefined;\n },\n\n get dev(): boolean {\n return process.env.NODE_ENV !== \"production\";\n },\n\n collection<PF extends Uppercase<string>, RemovePrefix extends boolean = false>(\n prefix: PF,\n options: Partial<{\n reviver: (value: string | undefined, key: string) => any;\n removePrefix: RemovePrefix;\n }> = {}\n ): Record<string, any> {\n const { reviver = (v) => v, removePrefix = false } = options;\n return Object.fromEntries(\n Object.entries(process.env)\n .filter(([key]) => key.startsWith(prefix))\n .map(([key, value]) => [\n removePrefix ? key.replace(prefix, \"\") : key,\n reviver(value, key),\n ])\n );\n },\n\n utils: Object.freeze({\n select<T, F>(\n key: Uppercase<string>,\n TRUE: T,\n FALSE: F,\n predicate: (key: Uppercase<string>, value: any) => boolean = (k) =>\n env.boolean(k)\n ): T | F {\n return predicate(key, process.env[key]) ? TRUE : FALSE;\n },\n }),\n get raw(){\n return Object.freeze(dotEnvVars)\n }\n});\n"],"names":["loadDotEnv","file","existsSync","text","readFileSync","line","key","rest","value","e","msg","dotEnvVars","k","v","env","_default","raw","val","prefix","options","reviver","removePrefix","TRUE","FALSE","predicate"],"mappings":"sGAEA,SAASA,EAAWC,EAAO,OAAQ,CAC/B,GAAI,CAACC,EAAAA,WAAWD,CAAI,QAAU,CAAA,EAE9B,GAAI,CACA,MAAME,EAAOC,EAAAA,aAAaH,EAAM,MAAM,EACtC,OAAO,OAAO,YACVE,EACK,MAAM,OAAO,EACb,OAAQE,GAASA,GAAQ,CAACA,EAAK,KAAA,EAAO,WAAW,GAAG,GAAKA,EAAK,SAAS,GAAG,CAAC,EAC3E,IAAKA,GAAS,CACX,KAAM,CAACC,EAAK,GAAGC,CAAI,EAAIF,EAAK,MAAM,GAAG,EACrC,IAAIG,EAAQD,EAAK,KAAK,GAAG,EAAE,KAAA,EAC3B,OACKC,EAAM,WAAW,GAAG,GAAKA,EAAM,SAAS,GAAG,GAC3CA,EAAM,WAAW,GAAG,GAAKA,EAAM,SAAS,GAAG,KAE5CA,EAAQA,EAAM,MAAM,EAAG,EAAE,GAEtB,CAACF,EAAI,KAAA,EAAQE,CAAK,CAC7B,CAAC,CAAA,CAEb,OAASC,EAAQ,CACb,MAAMC,EAAMD,GAAG,SAAW,sBAE1B,OAAI,WAAW,QAAQ,KAAM,WAAW,OAAO,KAAKC,CAAG,EAClD,QAAQ,KAAKA,CAAG,EACd,CAAA,CACX,CACJ,CAGA,MAAMC,EAAaX,EAAA,EACnB,SAAW,CAACY,EAAGC,CAAC,IAAK,OAAO,QAAQF,CAAU,EACpCC,KAAK,QAAQ,MAAM,QAAQ,IAAIA,CAAC,EAAIC,GAGvC,MAAMC,EAAM,OAAO,OAAO,CAC7B,OAAkCR,EAAwBS,EAAiB,CACvE,OAAMT,KAAO,QAAQ,cAAc,IAAIA,CAAG,EAAIS,GAAY,IACnD,QAAQ,IAAIT,CAAG,CAC1B,EAEA,OAAOA,EAAwBS,EAAW,EAAW,CACjD,MAAMC,EAAM,QAAQ,IAAIV,CAAG,EAC3B,GAAIU,IAAQ,OACR,eAAQ,IAAIV,CAAG,EAAI,OAAOS,CAAQ,EAC3BA,EAEX,MAAME,EAAM,OAAOD,CAAG,EACtB,OAAO,OAAO,SAASC,CAAG,EAAIA,EAAMF,CACxC,EAEA,QAAQT,EAAwBS,EAAW,GAAgB,CACvD,MAAMC,EAAM,QAAQ,IAAIV,CAAG,EAC3B,GAAIU,IAAQ,OACR,eAAQ,IAAIV,CAAG,EAAIS,EAAW,OAAS,QAChCA,EAEX,MAAME,EAAMD,EAAI,YAAA,EAChB,OAAOC,IAAQ,QAAUA,IAAQ,GACrC,EAEA,IAAIX,EAAiC,CACjC,OAAO,OAAO,UAAU,eAAe,KAAK,QAAQ,IAAKA,CAAG,CAChE,EAEA,QAAQA,EAAiC,CACrC,OAAOQ,EAAI,IAAIR,CAAG,GAAK,QAAQ,IAAIA,CAAG,IAAM,MAChD,EAEA,IAAI,KAAe,CACf,OAAO,QAAQ,IAAI,WAAa,YACpC,EAEA,WACIY,EACAC,EAGK,GACc,CACnB,KAAM,CAAE,QAAAC,EAAWP,GAAMA,EAAG,aAAAQ,EAAe,IAAUF,EACrD,OAAO,OAAO,YACV,OAAO,QAAQ,QAAQ,GAAG,EACrB,OAAO,CAAC,CAACb,CAAG,IAAMA,EAAI,WAAWY,CAAM,CAAC,EACxC,IAAI,CAAC,CAACZ,EAAKE,CAAK,IAAM,CACnBa,EAAef,EAAI,QAAQY,EAAQ,EAAE,EAAIZ,EACzCc,EAAQZ,EAAOF,CAAG,CAAA,CACrB,CAAA,CAEb,EAEA,MAAO,OAAO,OAAO,CACjB,OACIA,EACAgB,EACAC,EACAC,EAA8DZ,GAC1DE,EAAI,QAAQF,CAAC,EACZ,CACL,OAAOY,EAAUlB,EAAK,QAAQ,IAAIA,CAAG,CAAC,EAAIgB,EAAOC,CACrD,CAAA,CACH,EACD,IAAI,KAAK,CACL,OAAO,OAAO,OAAOZ,CAAU,CACnC,CACJ,CAAC"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/index.ts"],"sourcesContent":["import {readFileSync, existsSync} from \"fs\";\n\nfunction loadDotEnv(file = \".env\") {\n if (!existsSync(file)) return {};\n\n try {\n const text = readFileSync(file, \"utf8\");\n return Object.fromEntries(\n text\n .split(/\\r?\\n/)\n .filter((line) => line && !line.trim().startsWith(\"#\") && line.includes(\"=\"))\n .map((line) => {\n const [key, ...rest] = line.split(\"=\");\n let value = rest.join(\"=\").trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n return [key.trim(), value];\n })\n );\n } catch (e: any) {\n const msg = e?.message ?? \"Failed to load .env\";\n // @ts-ignore\n if (globalThis.logger?.warn) globalThis.logger.warn(msg);\n else console.warn(msg);\n return {};\n }\n}\n\n// merge .env into process.env at load\nconst dotEnvVars = loadDotEnv();\nfor (const [k, v] of Object.entries(dotEnvVars)) {\n if (!(k in process.env)) process.env[k] = v;\n}\n\nexport const env = Object.freeze({\n string<T extends string = string>(key: Uppercase<string>, _default?: T): T {\n if (!(key in process.env)) process.env[key] = _default ?? \"\";\n return process.env[key] as T;\n },\n\n number(key: Uppercase<string>, _default = 0): number {\n const raw = process.env[key];\n if (raw === undefined) {\n process.env[key] = String(_default);\n return _default;\n }\n const val = Number(raw);\n return Number.isFinite(val) ? val : _default;\n },\n\n boolean(key: Uppercase<string>, _default = false): boolean {\n const raw = process.env[key];\n if (raw === undefined) {\n process.env[key] = _default ? \"true\" : \"false\";\n return _default;\n }\n const val = raw.toLowerCase();\n return val === \"true\" || val === \"1\";\n },\n\n has(key: Uppercase<string>): boolean {\n return Object.prototype.hasOwnProperty.call(process.env, key);\n },\n assert(keys: Uppercase<string>[], error_builder: (missing_keys: string[]) => string | Error = ((missing_keys) => new Error(`Missing required keys(${missing_keys.join()}) in environment`)),) {\n const missing_keys: string[] = [];\n keys.forEach((key) => this.has(key) ? void 0: missing_keys.push(key));\n if (missing_keys.length > 0) {\n const result = error_builder(missing_keys);\n if (typeof result === \"string\") throw new Error(result);\n else throw result;\n }\n },\n defined(key: Uppercase<string>): boolean {\n return env.has(key) && process.env[key] !== undefined;\n },\n\n get dev(): boolean {\n return process.env.NODE_ENV !== \"production\";\n },\n\n collection<PF extends Uppercase<string>, RemovePrefix extends boolean = false>(\n prefix: PF,\n options: Partial<{\n reviver: (value: string | undefined, key: string) => any;\n removePrefix: RemovePrefix;\n }> = {}\n ): Record<string, any> {\n const {reviver = (v) => v, removePrefix = false} = options;\n return Object.fromEntries(\n Object.entries(process.env)\n .filter(([key]) => key.startsWith(prefix))\n .map(([key, value]) => [\n removePrefix ? key.replace(prefix, \"\") : key,\n reviver(value, key),\n ])\n );\n },\n\n utils: Object.freeze({\n select<T, F>(\n key: Uppercase<string>,\n TRUE: T,\n FALSE: F,\n predicate: (key: Uppercase<string>, value: any) => boolean = (k) =>\n env.boolean(k)\n ): T | F {\n return predicate(key, process.env[key]) ? TRUE : FALSE;\n },\n }),\n get raw() {\n return Object.freeze(dotEnvVars)\n }\n});\n"],"names":["loadDotEnv","file","existsSync","text","readFileSync","line","key","rest","value","e","msg","dotEnvVars","k","v","env","_default","raw","val","keys","error_builder","missing_keys","result","prefix","options","reviver","removePrefix","TRUE","FALSE","predicate"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export declare const env: Readonly<{
3
3
  number(key: Uppercase<string>, _default?: number): number;
4
4
  boolean(key: Uppercase<string>, _default?: boolean): boolean;
5
5
  has(key: Uppercase<string>): boolean;
6
+ assert(keys: Uppercase<string>[], error_builder?: (missing_keys: string[]) => string | Error): void;
6
7
  defined(key: Uppercase<string>): boolean;
7
8
  readonly dev: boolean;
8
9
  collection<PF extends Uppercase<string>, RemovePrefix extends boolean = false>(prefix: PF, options?: Partial<{
package/dist/index.es.js CHANGED
@@ -2,68 +2,75 @@ import { existsSync as a, readFileSync as v } from "fs";
2
2
  function l(e = ".env") {
3
3
  if (!a(e)) return {};
4
4
  try {
5
- const r = v(e, "utf8");
5
+ const t = v(e, "utf8");
6
6
  return Object.fromEntries(
7
- r.split(/\r?\n/).filter((t) => t && !t.trim().startsWith("#") && t.includes("=")).map((t) => {
8
- const [s, ...n] = t.split("=");
7
+ t.split(/\r?\n/).filter((r) => r && !r.trim().startsWith("#") && r.includes("=")).map((r) => {
8
+ const [s, ...n] = r.split("=");
9
9
  let o = n.join("=").trim();
10
10
  return (o.startsWith('"') && o.endsWith('"') || o.startsWith("'") && o.endsWith("'")) && (o = o.slice(1, -1)), [s.trim(), o];
11
11
  })
12
12
  );
13
- } catch (r) {
14
- const t = r?.message ?? "Failed to load .env";
15
- return globalThis.logger?.warn ? globalThis.logger.warn(t) : console.warn(t), {};
13
+ } catch (t) {
14
+ const r = t?.message ?? "Failed to load .env";
15
+ return globalThis.logger?.warn ? globalThis.logger.warn(r) : console.warn(r), {};
16
16
  }
17
17
  }
18
- const i = l();
19
- for (const [e, r] of Object.entries(i))
20
- e in process.env || (process.env[e] = r);
21
- const c = Object.freeze({
22
- string(e, r) {
23
- return e in process.env || (process.env[e] = r ?? ""), process.env[e];
18
+ const c = l();
19
+ for (const [e, t] of Object.entries(c))
20
+ e in process.env || (process.env[e] = t);
21
+ const i = Object.freeze({
22
+ string(e, t) {
23
+ return e in process.env || (process.env[e] = t ?? ""), process.env[e];
24
24
  },
25
- number(e, r = 0) {
26
- const t = process.env[e];
27
- if (t === void 0)
28
- return process.env[e] = String(r), r;
29
- const s = Number(t);
30
- return Number.isFinite(s) ? s : r;
25
+ number(e, t = 0) {
26
+ const r = process.env[e];
27
+ if (r === void 0)
28
+ return process.env[e] = String(t), t;
29
+ const s = Number(r);
30
+ return Number.isFinite(s) ? s : t;
31
31
  },
32
- boolean(e, r = !1) {
33
- const t = process.env[e];
34
- if (t === void 0)
35
- return process.env[e] = r ? "true" : "false", r;
36
- const s = t.toLowerCase();
32
+ boolean(e, t = !1) {
33
+ const r = process.env[e];
34
+ if (r === void 0)
35
+ return process.env[e] = t ? "true" : "false", t;
36
+ const s = r.toLowerCase();
37
37
  return s === "true" || s === "1";
38
38
  },
39
39
  has(e) {
40
40
  return Object.prototype.hasOwnProperty.call(process.env, e);
41
41
  },
42
+ assert(e, t = ((r) => new Error(`Missing required keys(${r.join()}) in environment`))) {
43
+ const r = [];
44
+ if (e.forEach((s) => this.has(s) ? void 0 : r.push(s)), r.length > 0) {
45
+ const s = t(r);
46
+ throw typeof s == "string" ? new Error(s) : s;
47
+ }
48
+ },
42
49
  defined(e) {
43
- return c.has(e) && process.env[e] !== void 0;
50
+ return i.has(e) && process.env[e] !== void 0;
44
51
  },
45
52
  get dev() {
46
53
  return process.env.NODE_ENV !== "production";
47
54
  },
48
- collection(e, r = {}) {
49
- const { reviver: t = (n) => n, removePrefix: s = !1 } = r;
55
+ collection(e, t = {}) {
56
+ const { reviver: r = (n) => n, removePrefix: s = !1 } = t;
50
57
  return Object.fromEntries(
51
58
  Object.entries(process.env).filter(([n]) => n.startsWith(e)).map(([n, o]) => [
52
59
  s ? n.replace(e, "") : n,
53
- t(o, n)
60
+ r(o, n)
54
61
  ])
55
62
  );
56
63
  },
57
64
  utils: Object.freeze({
58
- select(e, r, t, s = (n) => c.boolean(n)) {
59
- return s(e, process.env[e]) ? r : t;
65
+ select(e, t, r, s = (n) => i.boolean(n)) {
66
+ return s(e, process.env[e]) ? t : r;
60
67
  }
61
68
  }),
62
69
  get raw() {
63
- return Object.freeze(i);
70
+ return Object.freeze(c);
64
71
  }
65
72
  });
66
73
  export {
67
- c as env
74
+ i as env
68
75
  };
69
76
  //# sourceMappingURL=index.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/index.ts"],"sourcesContent":["import { readFileSync, existsSync } from \"fs\";\n\nfunction loadDotEnv(file = \".env\") {\n if (!existsSync(file)) return {};\n\n try {\n const text = readFileSync(file, \"utf8\");\n return Object.fromEntries(\n text\n .split(/\\r?\\n/)\n .filter((line) => line && !line.trim().startsWith(\"#\") && line.includes(\"=\"))\n .map((line) => {\n const [key, ...rest] = line.split(\"=\");\n let value = rest.join(\"=\").trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n return [key.trim(), value];\n })\n );\n } catch (e: any) {\n const msg = e?.message ?? \"Failed to load .env\";\n // @ts-ignore\n if (globalThis.logger?.warn) globalThis.logger.warn(msg);\n else console.warn(msg);\n return {};\n }\n}\n\n// merge .env into process.env at load\nconst dotEnvVars = loadDotEnv();\nfor (const [k, v] of Object.entries(dotEnvVars)) {\n if (!(k in process.env)) process.env[k] = v;\n}\n\nexport const env = Object.freeze({\n string<T extends string = string>(key: Uppercase<string>, _default?: T): T {\n if (!(key in process.env)) process.env[key] = _default ?? \"\";\n return process.env[key] as T;\n },\n\n number(key: Uppercase<string>, _default = 0): number {\n const raw = process.env[key];\n if (raw === undefined) {\n process.env[key] = String(_default);\n return _default;\n }\n const val = Number(raw);\n return Number.isFinite(val) ? val : _default;\n },\n\n boolean(key: Uppercase<string>, _default = false): boolean {\n const raw = process.env[key];\n if (raw === undefined) {\n process.env[key] = _default ? \"true\" : \"false\";\n return _default;\n }\n const val = raw.toLowerCase();\n return val === \"true\" || val === \"1\";\n },\n\n has(key: Uppercase<string>): boolean {\n return Object.prototype.hasOwnProperty.call(process.env, key);\n },\n\n defined(key: Uppercase<string>): boolean {\n return env.has(key) && process.env[key] !== undefined;\n },\n\n get dev(): boolean {\n return process.env.NODE_ENV !== \"production\";\n },\n\n collection<PF extends Uppercase<string>, RemovePrefix extends boolean = false>(\n prefix: PF,\n options: Partial<{\n reviver: (value: string | undefined, key: string) => any;\n removePrefix: RemovePrefix;\n }> = {}\n ): Record<string, any> {\n const { reviver = (v) => v, removePrefix = false } = options;\n return Object.fromEntries(\n Object.entries(process.env)\n .filter(([key]) => key.startsWith(prefix))\n .map(([key, value]) => [\n removePrefix ? key.replace(prefix, \"\") : key,\n reviver(value, key),\n ])\n );\n },\n\n utils: Object.freeze({\n select<T, F>(\n key: Uppercase<string>,\n TRUE: T,\n FALSE: F,\n predicate: (key: Uppercase<string>, value: any) => boolean = (k) =>\n env.boolean(k)\n ): T | F {\n return predicate(key, process.env[key]) ? TRUE : FALSE;\n },\n }),\n get raw(){\n return Object.freeze(dotEnvVars)\n }\n});\n"],"names":["loadDotEnv","file","existsSync","text","readFileSync","line","key","rest","value","e","msg","dotEnvVars","k","v","env","_default","raw","val","prefix","options","reviver","removePrefix","TRUE","FALSE","predicate"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/index.ts"],"sourcesContent":["import {readFileSync, existsSync} from \"fs\";\n\nfunction loadDotEnv(file = \".env\") {\n if (!existsSync(file)) return {};\n\n try {\n const text = readFileSync(file, \"utf8\");\n return Object.fromEntries(\n text\n .split(/\\r?\\n/)\n .filter((line) => line && !line.trim().startsWith(\"#\") && line.includes(\"=\"))\n .map((line) => {\n const [key, ...rest] = line.split(\"=\");\n let value = rest.join(\"=\").trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n return [key.trim(), value];\n })\n );\n } catch (e: any) {\n const msg = e?.message ?? \"Failed to load .env\";\n // @ts-ignore\n if (globalThis.logger?.warn) globalThis.logger.warn(msg);\n else console.warn(msg);\n return {};\n }\n}\n\n// merge .env into process.env at load\nconst dotEnvVars = loadDotEnv();\nfor (const [k, v] of Object.entries(dotEnvVars)) {\n if (!(k in process.env)) process.env[k] = v;\n}\n\nexport const env = Object.freeze({\n string<T extends string = string>(key: Uppercase<string>, _default?: T): T {\n if (!(key in process.env)) process.env[key] = _default ?? \"\";\n return process.env[key] as T;\n },\n\n number(key: Uppercase<string>, _default = 0): number {\n const raw = process.env[key];\n if (raw === undefined) {\n process.env[key] = String(_default);\n return _default;\n }\n const val = Number(raw);\n return Number.isFinite(val) ? val : _default;\n },\n\n boolean(key: Uppercase<string>, _default = false): boolean {\n const raw = process.env[key];\n if (raw === undefined) {\n process.env[key] = _default ? \"true\" : \"false\";\n return _default;\n }\n const val = raw.toLowerCase();\n return val === \"true\" || val === \"1\";\n },\n\n has(key: Uppercase<string>): boolean {\n return Object.prototype.hasOwnProperty.call(process.env, key);\n },\n assert(keys: Uppercase<string>[], error_builder: (missing_keys: string[]) => string | Error = ((missing_keys) => new Error(`Missing required keys(${missing_keys.join()}) in environment`)),) {\n const missing_keys: string[] = [];\n keys.forEach((key) => this.has(key) ? void 0: missing_keys.push(key));\n if (missing_keys.length > 0) {\n const result = error_builder(missing_keys);\n if (typeof result === \"string\") throw new Error(result);\n else throw result;\n }\n },\n defined(key: Uppercase<string>): boolean {\n return env.has(key) && process.env[key] !== undefined;\n },\n\n get dev(): boolean {\n return process.env.NODE_ENV !== \"production\";\n },\n\n collection<PF extends Uppercase<string>, RemovePrefix extends boolean = false>(\n prefix: PF,\n options: Partial<{\n reviver: (value: string | undefined, key: string) => any;\n removePrefix: RemovePrefix;\n }> = {}\n ): Record<string, any> {\n const {reviver = (v) => v, removePrefix = false} = options;\n return Object.fromEntries(\n Object.entries(process.env)\n .filter(([key]) => key.startsWith(prefix))\n .map(([key, value]) => [\n removePrefix ? key.replace(prefix, \"\") : key,\n reviver(value, key),\n ])\n );\n },\n\n utils: Object.freeze({\n select<T, F>(\n key: Uppercase<string>,\n TRUE: T,\n FALSE: F,\n predicate: (key: Uppercase<string>, value: any) => boolean = (k) =>\n env.boolean(k)\n ): T | F {\n return predicate(key, process.env[key]) ? TRUE : FALSE;\n },\n }),\n get raw() {\n return Object.freeze(dotEnvVars)\n }\n});\n"],"names":["loadDotEnv","file","existsSync","text","readFileSync","line","key","rest","value","e","msg","dotEnvVars","k","v","env","_default","raw","val","keys","error_builder","missing_keys","result","prefix","options","reviver","removePrefix","TRUE","FALSE","predicate"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sourceregistry/node-env",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A minimal, dependency-free TypeScript/JavaScript library for environment-variable loading and typed access.",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "module": "./dist/index.es.js",