@mostajs/env-manager 0.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 +5 -0
- package/llms.txt +9 -0
- package/package.json +30 -0
- package/src/index.js +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# @mostajs/env-manager
|
|
2
|
+
|
|
3
|
+
**Auteur** : Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
Gestionnaire de fichiers **`.env`** : lecture, application dans `process.env`, et **persistance** (mise à jour des lignes existantes + ajout des nouvelles, commentaires préservés). Sans dépendance. Extrait de l app AgoraScope.
|
package/llms.txt
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @mostajs/env-manager — fiche LLM
|
|
2
|
+
> Gestionnaire de fichiers .env : lecture, application (process.env), persistance (update lignes + ajout). Sans dépendance.
|
|
3
|
+
|
|
4
|
+
## EXPORTS
|
|
5
|
+
parseEnv(text) -> obj · readEnvFile(path) -> obj · applyEnvFile(path,{env,override}) -> appliquées · updateEnvFile(path,kv) -> bool (persiste, préserve commentaires/ordre) · createEnvManager(path,{env}) -> { read, apply, update(=persiste+applique), get, path }
|
|
6
|
+
|
|
7
|
+
## PIÈGES
|
|
8
|
+
- applyEnvFile : override=false (défaut) → l env SYSTÈME prévaut sur le fichier.
|
|
9
|
+
- updateEnvFile : met à jour les lignes existantes, AJOUTE les nouvelles, conserve commentaires.
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mostajs/env-manager",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Gestionnaire de fichiers .env : lecture, application dans process.env, et persistance (update des lignes + ajout). Sans dépendance.",
|
|
5
|
+
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
|
+
"license": "AGPL-3.0-or-later",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./src/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"src",
|
|
14
|
+
"README.md",
|
|
15
|
+
"llms.txt"
|
|
16
|
+
],
|
|
17
|
+
"keywords": [
|
|
18
|
+
"dotenv",
|
|
19
|
+
"env",
|
|
20
|
+
"config",
|
|
21
|
+
"persistence",
|
|
22
|
+
"mostajs"
|
|
23
|
+
],
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@mostajs/mjs-unit": "^0.3.0"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "node test-scripts/unit/env-manager.test.mjs && node examples/run.mjs"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// @mostajs/env-manager — gestionnaire de fichiers .env : lecture, application (process.env),
|
|
2
|
+
// et PERSISTANCE (mise à jour des lignes, ajout des nouvelles). Sans dépendance. LOGIQUE PURE + I/O fichier.
|
|
3
|
+
// @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
|
|
6
|
+
/** Parse un texte .env → objet { CLE: valeur } (commentaires/ lignes vides ignorés ; guillemets retirés). */
|
|
7
|
+
export function parseEnv(text = '') {
|
|
8
|
+
const out = {};
|
|
9
|
+
for (const line of String(text).split('\n')) {
|
|
10
|
+
const m = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/);
|
|
11
|
+
if (m && !line.trimStart().startsWith('#')) out[m[1]] = m[2].replace(/^["']|["']$/g, '');
|
|
12
|
+
}
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Lit un fichier .env → objet (vide si absent). */
|
|
17
|
+
export function readEnvFile(path) { try { return parseEnv(fs.readFileSync(path, 'utf8')); } catch { return {}; } }
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Applique un .env dans process.env (ou un env cible).
|
|
21
|
+
* @param {string} path
|
|
22
|
+
* @param {{ env?, override? }} [opts] override=false (défaut) : l'env système prévaut sur le fichier.
|
|
23
|
+
* @returns {object} les paires effectivement appliquées
|
|
24
|
+
*/
|
|
25
|
+
export function applyEnvFile(path, { env = process.env, override = false } = {}) {
|
|
26
|
+
const parsed = readEnvFile(path); const applied = {};
|
|
27
|
+
for (const [k, v] of Object.entries(parsed)) if (override || env[k] === undefined) { env[k] = v; applied[k] = v; }
|
|
28
|
+
return applied;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* PERSISTE des paires clé=valeur dans le fichier .env : met à jour les lignes existantes,
|
|
33
|
+
* ajoute les nouvelles, **préserve** commentaires et ordre. Crée le fichier au besoin.
|
|
34
|
+
* @returns {boolean} succès
|
|
35
|
+
*/
|
|
36
|
+
export function updateEnvFile(path, kv = {}) {
|
|
37
|
+
let lines = []; try { lines = fs.readFileSync(path, 'utf8').split('\n'); } catch { /* nouveau */ }
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
lines = lines.map((l) => { const m = l.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/); if (m && kv[m[1]] !== undefined) { seen.add(m[1]); return `${m[1]}=${kv[m[1]]}`; } return l; });
|
|
40
|
+
for (const [k, v] of Object.entries(kv)) if (!seen.has(k)) lines.push(`${k}=${v}`);
|
|
41
|
+
// TOUJOURS terminer par un saut de ligne (sinon un append externe se concatène à la dernière ligne).
|
|
42
|
+
try { fs.writeFileSync(path, lines.join('\n').replace(/\n+$/, '') + '\n'); return true; } catch { return false; }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Façade pratique : un gestionnaire lié à un chemin. */
|
|
46
|
+
export function createEnvManager(path, { env = process.env } = {}) {
|
|
47
|
+
return {
|
|
48
|
+
path,
|
|
49
|
+
read: () => readEnvFile(path),
|
|
50
|
+
apply: (opts) => applyEnvFile(path, { env, ...opts }),
|
|
51
|
+
update: (kv) => { const ok = updateEnvFile(path, kv); if (ok) Object.assign(env, kv); return ok; }, // persiste + applique au runtime
|
|
52
|
+
get: (k) => readEnvFile(path)[k],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export default { parseEnv, readEnvFile, applyEnvFile, updateEnvFile, createEnvManager };
|