diff --git a/package.json b/package.json index bf5da6e..573970d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/use-config", - "version": "1.0.10", + "version": "1.0.11", "types": "dist/config.d.ts", "scripts": { "build": "npm run clean && tsup", @@ -20,13 +20,13 @@ "license": "UNLICENSED", "type": "module", "devDependencies": { - "@types/node": "^22.13.5", - "dotenv": "^16.4.7", - "fast-glob": "^3.3.2", + "@types/node": "^22.14.1", + "dotenv": "^16.5.0", + "fast-glob": "^3.3.3", "json-schema-to-ts": "^3.1.1", "json5": "^2.2.3", "tsup": "^8.4.0", - "typescript": "^5.7.3" + "typescript": "^5.8.3" }, "exports": { ".": { @@ -54,6 +54,6 @@ "dotenv": "^16.4.7" }, "dependencies": { - "@kevisual/load": "^0.0.4" + "@kevisual/load": "^0.0.6" } } \ No newline at end of file diff --git a/src/env.ts b/src/env.ts index 34ae457..e8d91a4 100644 --- a/src/env.ts +++ b/src/env.ts @@ -4,39 +4,33 @@ import dotenv from 'dotenv'; // 配置类型 export type Config = { - port: number; - tokenSecret?: string; - redis?: { - host?: string; - port?: number; - password?: string; - version?: string; - [key: string]: any; - }; - posgtres?: { - host?: string; - port?: number; - user?: string; - password?: string; - database?: string; - [key: string]: any; - }; - minio?: { - endPoint?: string; - bucketName?: string; - useSSL?: boolean; - accessKey?: string; - secretKey?: string; - [key: string]: any; - }; - mongo?: { - uri?: string; - [key: string]: any; - }; + PORT: number; + // redis + REDIS_HOST?: string; + REDIS_PORT?: number; + REDIS_PASSWORD?: string; + REDIS_VERSION?: string; + REDIS_DB?: number; + REDIS_USER?: string; + // postgres + POSTGRES_HOST?: string; + POSTGRES_PORT?: number; + POSTGRES_PASSWORD?: string; + POSTGRES_USER?: string; + POSTGRES_DB?: string; + // minio + MINIO_ENDPOINT?: string; + MINIO_BUCKET_NAME?: string; + MINIO_ACCESS_KEY?: string; + MINIO_SECRET_KEY?: string; + MINIO_USE_SSL?: boolean; + // mongo + MONGO_URI?: string; + // [key: string]: any; }; export const initConfig: Config = { - port: 3000, + PORT: 3000, }; export const fileIsExist = (path: string) => { try { @@ -49,9 +43,21 @@ export const fileIsExist = (path: string) => { export const getDirname = () => { return process.cwd(); }; -type ConfigOpts = { +/** + * 配置选项 + */ +export type ConfigOpts = { + /** + * 环境配置文件路径, default: 自定设置,优先级最高, process.cwd() + envConfigFile + */ envConfigFile?: string; + /** + * 当前工作目录, default: process.cwd() + */ cwd?: string; + /** + * 配置文件名, default: .env + */ fileName?: string; }; /** @@ -82,9 +88,17 @@ export const getConfigFile = (opts?: ConfigOpts) => { if (lastLast) return lastLastPath; return ''; }; - -// 初始化读取配置文件 -export const init = (opts?: ConfigOpts & { dotenvOpts?: dotenv.DotenvConfigOptions }): Config => { +type GetConfigOpts = ConfigOpts & { dotenvOpts?: dotenv.DotenvConfigOptions }; +/** + * 初始化配置, 不会把配置内容挂载到全局 + * @param opts 配置选项 + * @param opts.envConfigFile 环境配置文件路径, default: 为空,process.cwd() + envConfigFile + * @param opts.cwd 当前工作目录, default: process.cwd() + * @param opts.fileName 配置文件名, default: .env + * @param opts.dotenvOpts dotenv配置选项 + * @returns 配置 + */ +export const getConfig = (opts?: GetConfigOpts): Config => { if (opts?.dotenvOpts) { const prased = dotenv.config(opts.dotenvOpts).parsed as Config; if (prased) { @@ -109,13 +123,28 @@ export const init = (opts?: ConfigOpts & { dotenvOpts?: dotenv.DotenvConfigOptio * * @returns Config */ -export const useConfig = (): Config & T => { +export const useConfig = (onlyInitConfig?: GetConfigOpts): Config & T => { const config = (global as any).config; - const _config = config || init(); + const _config = config || getConfig(onlyInitConfig); !config && ((global as any)['config'] = _config); return _config; }; +/** + * 更新配置 + * @param configOpts 配置 + * @param opts 配置选项 + * @param opts.cwd 当前工作目录, default: process.cwd() + * @param opts.fileName 配置文件名, default: config.json + */ +export const updateConfig = (configOpts: GetConfigOpts) => { + const _config = (global as any).config || {}; + const newConfig = getConfig(configOpts); + Object.assign(_config, newConfig); + (global as any).config = _config; + return _config; +}; + export const useKey = (key: string, opts?: { defaultValue?: string; isNumber?: boolean; isBoolean?: boolean }): string | number | boolean => { let v = useConfig()[key]; if (!v) { @@ -124,11 +153,46 @@ export const useKey = (key: string, opts?: { defaultValue?: string; isNumber?: b if (!v) { return opts?.defaultValue || null; } - if (opts?.isNumber) { + if (opts?.isNumber && typeof v === 'string') { return Number(v); } - if (opts?.isBoolean) { + if (opts?.isBoolean && typeof v === 'string') { return v === 'true'; } return v; }; + +/** + * 写入json配置文件 + * @param config 配置 + * @param opts 配置选项 + * @param opts.cwd 当前工作目录, default: process.cwd() + * @param opts.fileName 配置文件名, default: config.json + */ +export const writeJsonConfig = (config = {}, opts?: Omit) => { + const filePath = getConfigFile({ ...opts, fileName: opts?.fileName || 'config.json' }); + if (!filePath) { + throw new Error(`未找到配置文件: ${opts?.fileName || 'config.json'}`); + } + fs.writeFileSync(filePath, JSON.stringify(config, null, 2)); +}; + +/** + * 读取json配置文件 + * @param opts 配置选项 + * @param opts.cwd 当前工作目录, default: process.cwd() + * @param opts.fileName 配置文件名, default: config.json + * @returns 配置 + */ +export const readJsonConfig = (opts?: Omit) => { + const filePath = getConfigFile({ ...opts, fileName: opts?.fileName || 'config.json' }); + if (!filePath) { + throw new Error(`未找到配置文件: ${opts?.fileName || 'config.json'}`); + } + try { + const value = JSON.parse(fs.readFileSync(filePath, 'utf-8')); + return value; + } catch (e) { + return {}; + } +};