loony-dotenv 0.1.0 → 0.1.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/lib/index.d.ts +6 -0
- package/lib/index.js +70 -0
- package/package.json +23 -4
- package/index.mjs +0 -81
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
/**
|
|
9
|
+
* Safely parse a single line of KEY=VALUE format.
|
|
10
|
+
* Supports quoted values and inline comments.
|
|
11
|
+
* @param {string} line
|
|
12
|
+
* @returns {{ key: string, value: string } | null}
|
|
13
|
+
*/
|
|
14
|
+
function parseEnvLine(line) {
|
|
15
|
+
const trimmed = line.trim();
|
|
16
|
+
// Skip blank lines and comment lines
|
|
17
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
18
|
+
return null;
|
|
19
|
+
// Find first '=' that isn't escaped
|
|
20
|
+
let separatorIndex = -1;
|
|
21
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
22
|
+
if (trimmed[i] === "=" && trimmed[i - 1] !== "\\") {
|
|
23
|
+
separatorIndex = i;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (separatorIndex === -1) {
|
|
28
|
+
console.warn(`[loony-dotenv] Skipping malformed line: ${trimmed}`);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const key = trimmed.slice(0, separatorIndex).trim();
|
|
32
|
+
let value = trimmed.slice(separatorIndex + 1).trim();
|
|
33
|
+
// Remove inline comments: KEY=value # comment
|
|
34
|
+
const commentIndex = value.indexOf(" #");
|
|
35
|
+
if (commentIndex !== -1) {
|
|
36
|
+
value = value.slice(0, commentIndex).trim();
|
|
37
|
+
}
|
|
38
|
+
// Remove surrounding quotes
|
|
39
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
40
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
41
|
+
value = value.slice(1, -1);
|
|
42
|
+
}
|
|
43
|
+
// Unescape escaped '=' (i.e., KEY=va\=lue)
|
|
44
|
+
value = value.replace(/\\=/g, "=");
|
|
45
|
+
return { key, value };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Loads variables from a .env file into process.env.
|
|
49
|
+
* @param {string} envPath - Path to .env file (default: ".env")
|
|
50
|
+
*/
|
|
51
|
+
function loadEnv(envPath = ".env") {
|
|
52
|
+
const absolutePath = path_1.default.resolve(envPath);
|
|
53
|
+
if (!fs_1.default.existsSync(absolutePath)) {
|
|
54
|
+
console.error(`[loony-dotenv] .env file not found at: ${absolutePath}`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const fileContents = fs_1.default.readFileSync(absolutePath, "utf8");
|
|
58
|
+
const lines = fileContents.split(/\r?\n/);
|
|
59
|
+
for (const line of lines) {
|
|
60
|
+
const parsed = parseEnvLine(line);
|
|
61
|
+
if (!parsed)
|
|
62
|
+
continue;
|
|
63
|
+
const { key, value } = parsed;
|
|
64
|
+
// Do not override existing environment variables
|
|
65
|
+
if (!(key in process.env)) {
|
|
66
|
+
process.env[key] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.default = loadEnv;
|
package/package.json
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loony-dotenv",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Simple environment loader that reads .env files and automatically populates process.env for Node.js applications.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
6
|
+
"private": false,
|
|
7
|
+
"main": "./lib/index.js",
|
|
8
|
+
"types": "./lib/index.d.ts",
|
|
7
9
|
"exports": {
|
|
8
|
-
".":
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./lib/index.d.ts",
|
|
12
|
+
"import": "./lib/index.js"
|
|
13
|
+
}
|
|
9
14
|
},
|
|
10
15
|
"files": [
|
|
11
|
-
"
|
|
16
|
+
"lib"
|
|
12
17
|
],
|
|
13
18
|
"keywords": [
|
|
14
19
|
"loony-env",
|
|
@@ -21,5 +26,19 @@
|
|
|
21
26
|
"repository": {
|
|
22
27
|
"type": "git",
|
|
23
28
|
"url": "https://github.com/loony-js/loony-dotenv.git"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "npm run clean && tsc",
|
|
32
|
+
"clean": "rm -rf lib",
|
|
33
|
+
"dev": "ts-node index.ts",
|
|
34
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^25.0.3",
|
|
38
|
+
"ts-node": "^10.9.2",
|
|
39
|
+
"typescript": "^5.9.3"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
24
43
|
}
|
|
25
44
|
}
|
package/index.mjs
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Safely parse a single line of KEY=VALUE format.
|
|
6
|
-
* Supports quoted values and inline comments.
|
|
7
|
-
* @param {string} line
|
|
8
|
-
* @returns {{ key: string, value: string } | null}
|
|
9
|
-
*/
|
|
10
|
-
function parseEnvLine(line) {
|
|
11
|
-
const trimmed = line.trim();
|
|
12
|
-
|
|
13
|
-
// Skip blank lines and comment lines
|
|
14
|
-
if (!trimmed || trimmed.startsWith("#")) return null;
|
|
15
|
-
|
|
16
|
-
// Find first '=' that isn't escaped
|
|
17
|
-
let separatorIndex = -1;
|
|
18
|
-
for (let i = 0; i < trimmed.length; i++) {
|
|
19
|
-
if (trimmed[i] === "=" && trimmed[i - 1] !== "\\") {
|
|
20
|
-
separatorIndex = i;
|
|
21
|
-
break;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (separatorIndex === -1) {
|
|
26
|
-
console.warn(`[loony-dotenv] Skipping malformed line: ${trimmed}`);
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const key = trimmed.slice(0, separatorIndex).trim();
|
|
31
|
-
let value = trimmed.slice(separatorIndex + 1).trim();
|
|
32
|
-
|
|
33
|
-
// Remove inline comments: KEY=value # comment
|
|
34
|
-
const commentIndex = value.indexOf(" #");
|
|
35
|
-
if (commentIndex !== -1) {
|
|
36
|
-
value = value.slice(0, commentIndex).trim();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Remove surrounding quotes
|
|
40
|
-
if (
|
|
41
|
-
(value.startsWith('"') && value.endsWith('"')) ||
|
|
42
|
-
(value.startsWith("'") && value.endsWith("'"))
|
|
43
|
-
) {
|
|
44
|
-
value = value.slice(1, -1);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Unescape escaped '=' (i.e., KEY=va\=lue)
|
|
48
|
-
value = value.replace(/\\=/g, "=");
|
|
49
|
-
|
|
50
|
-
return { key, value };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Loads variables from a .env file into process.env.
|
|
55
|
-
* @param {string} envPath - Path to .env file (default: ".env")
|
|
56
|
-
*/
|
|
57
|
-
function loadEnv(envPath = ".env") {
|
|
58
|
-
const absolutePath = path.resolve(envPath);
|
|
59
|
-
|
|
60
|
-
if (!fs.existsSync(absolutePath)) {
|
|
61
|
-
console.error(`[loony-dotenv] .env file not found at: ${absolutePath}`);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const fileContents = fs.readFileSync(absolutePath, "utf8");
|
|
66
|
-
const lines = fileContents.split(/\r?\n/);
|
|
67
|
-
|
|
68
|
-
for (const line of lines) {
|
|
69
|
-
const parsed = parseEnvLine(line);
|
|
70
|
-
if (!parsed) continue;
|
|
71
|
-
|
|
72
|
-
const { key, value } = parsed;
|
|
73
|
-
|
|
74
|
-
// Do not override existing environment variables
|
|
75
|
-
if (!(key in process.env)) {
|
|
76
|
-
process.env[key] = value;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export default loadEnv;
|