123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- import path from "path";
- import {fileURLToPath} from "url";
- import {existsSync, readFileSync, writeFileSync, unlinkSync} from "fs";
- import {LRUCache} from "lru-cache";
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
- const _envPath = path.join(__dirname, "../config/env.json");
- const _lockPath = `${_envPath}.lock`;
- // 创建 LRU 缓存实例
- const cache = new LRUCache({
- max: 100, // 最大缓存条目数
- ttl: 1000 * 60 * 5, // 缓存时间(毫秒),例如 5 分钟
- });
- // 定义用于缓存整个对象的特殊键
- const FULL_ENV_CACHE_KEY = "__FULL_ENV__";
- export const ENV = {
- _envPath,
- _lockPath,
- _envObj: {},
- /**
- * 读取环境变量文件并解析为对象
- * @private
- * @returns {Object} 解析后的环境变量对象
- */
- _readEnvFile() {
- if (!existsSync(this._envPath)) {
- return {};
- }
- try {
- const content = readFileSync(this._envPath, "utf-8");
- return JSON.parse(content);
- } catch (e) {
- console.error(`Failed to read or parse env file: ${e.message}`);
- return {};
- }
- },
- /**
- * 写入环境变量文件(带锁文件机制)
- * @private
- * @param {Object} envObj 环境变量对象
- */
- _writeEnvFile(envObj) {
- // 尝试创建锁文件
- if (existsSync(this._lockPath)) {
- console.error("Another process is currently writing to the env file.");
- throw new Error("File is locked. Please retry later.");
- }
- try {
- // 创建锁文件
- writeFileSync(this._lockPath, "LOCK", "utf-8");
- // 写入环境变量文件
- writeFileSync(this._envPath, JSON.stringify(envObj, null, 2), "utf-8");
- } catch (e) {
- console.error(`Failed to write to env file: ${e.message}`);
- } finally {
- // 移除锁文件
- if (existsSync(this._lockPath)) {
- unlinkSync(this._lockPath);
- }
- }
- },
- /**
- * 获取环境变量(支持缓存)
- * @param {string} [key] 可选,获取特定键的值或完整对象
- * @param _value 默认值
- * @param isObject 是否为对象格式,默认为0
- * @returns {string|Object} 环境变量值或完整对象
- */
- get(key, _value = '', isObject = 0) {
- if (!key) {
- // 不传参时获取整个对象
- if (cache.has(FULL_ENV_CACHE_KEY)) {
- return cache.get(FULL_ENV_CACHE_KEY);
- }
- const envObj = this._readEnvFile();
- cache.set(FULL_ENV_CACHE_KEY, envObj);
- return envObj;
- }
- // 传参时获取特定键
- if (cache.has(key)) {
- // console.log(`从内存缓存中读取: ${key}`);
- return cache.get(key);
- }
- console.log(`从文件中读取: ${key}`);
- const envObj = this._readEnvFile();
- let value = envObj[key] || _value;
- // 如果是对象格式,但value不是对象。则转换
- if (isObject && typeof value !== 'object') {
- try {
- value = JSON.parse(value);
- } catch (e) {
- value = {};
- console.error(`Failed to parse value for key "${key}" as object: ${e.message}`);
- }
- }
- // 写入缓存
- cache.set(key, value);
- return value;
- },
- /**
- * 设置环境变量
- * @param {string} key 键名
- * @param {string|Object} [value=''] 键值
- * @param {number} [isObject=0] 是否为对象格式,默认为0
- */
- set(key, value = "", isObject = 0) {
- if (!key || typeof key !== "string") {
- throw new Error("Key must be a non-empty string.");
- }
- // 如果是对象格式,但value不是对象。则转换
- if (isObject && typeof value !== 'object') {
- try {
- value = JSON.parse(value);
- } catch (e) {
- value = {};
- console.error(`Failed to parse value for key "${key}" as object: ${e.message}`);
- }
- }
- const envObj = this._readEnvFile();
- envObj[key] = value;
- this._writeEnvFile(envObj);
- // 清除对应键和整个对象的缓存
- cache.delete(key);
- cache.delete(FULL_ENV_CACHE_KEY);
- },
- /**
- * 删除环境变量
- * @param {string} key 键名
- */
- delete(key) {
- if (!key || typeof key !== "string") {
- throw new Error("Key must be a non-empty string.");
- }
- const envObj = this._readEnvFile();
- if (key in envObj) {
- delete envObj[key];
- this._writeEnvFile(envObj);
- // 清除对应键和整个对象的缓存
- cache.delete(key);
- cache.delete(FULL_ENV_CACHE_KEY);
- } else {
- console.warn(`Key "${key}" does not exist in env file.`);
- }
- },
- };
|