diff --git a/.gitignore b/.gitignore index 1d743a4..e9f0ed1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ dist app.config.json5 + +.env diff --git a/demo/package.json b/demo/package.json index b821b07..dee79f5 100644 --- a/demo/package.json +++ b/demo/package.json @@ -11,6 +11,6 @@ "license": "MIT", "type": "module", "dependencies": { - "@kevisual/user-config": "link:.." + "@kevisual/use-config": "link:.." } } diff --git a/demo/src/env.ts b/demo/src/env.ts new file mode 100644 index 0000000..511f2e8 --- /dev/null +++ b/demo/src/env.ts @@ -0,0 +1,9 @@ +import fs from 'fs'; +import { useConfig, useKey } from '@kevisual/use-config/env'; +const config = useConfig(); + +console.log(config); + +const a = useKey('a'); + +console.log(a); diff --git a/demo/src/index.ts b/demo/src/index.ts index a1dec1b..9add667 100644 --- a/demo/src/index.ts +++ b/demo/src/index.ts @@ -1,4 +1,4 @@ -import { useConfig } from '@kevisual/user-config'; +import { useConfig } from '@kevisual/use-config'; // console.log(useConfig); console.log(useConfig()); diff --git a/demo/tsconfig.json b/demo/tsconfig.json new file mode 100644 index 0000000..918f972 --- /dev/null +++ b/demo/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "target": "esnext", + "noImplicitAny": false, + "outDir": "./dist", + "sourceMap": false, + "allowJs": true, + "newLine": "LF", + "baseUrl": "./", + "typeRoots": [ + "node_modules/@types", + ], + "declaration": false, + "noEmit": true, + "allowImportingTsExtensions": true, + "moduleResolution": "NodeNext", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "paths": { + "@/*": [ + "src/*" + ], + } + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules", + "rollup.config.js", + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 978339d..bf5da6e 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "@kevisual/use-config", - "version": "1.0.9", + "version": "1.0.10", "types": "dist/config.d.ts", "scripts": { - "build": "npm run clean && rollup -c", - "watch": " rollup -c -w", + "build": "npm run clean && tsup", + "watch": "tsup --watch", "clean": "rimraf dist" }, "publishConfig": { @@ -20,24 +20,12 @@ "license": "UNLICENSED", "type": "module", "devDependencies": { - "@rollup/plugin-alias": "^5.1.1", - "@rollup/plugin-commonjs": "^28.0.2", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^16.0.0", - "@rollup/plugin-replace": "^6.0.2", - "@rollup/plugin-typescript": "^12.1.2", "@types/node": "^22.13.5", - "chalk": "^5.4.1", - "commander": "^13.1.0", - "glob": "^11.0.1", + "dotenv": "^16.4.7", + "fast-glob": "^3.3.2", "json-schema-to-ts": "^3.1.1", "json5": "^2.2.3", - "rollup": "^4.34.8", - "rollup-plugin-copy": "^3.5.0", - "rollup-plugin-dts": "^6.1.1", - "rollup-plugin-esbuild": "^6.2.0", - "rollup-plugin-inject": "^3.0.2", - "tslib": "^2.8.1", + "tsup": "^8.4.0", "typescript": "^5.7.3" }, "exports": { @@ -45,6 +33,10 @@ "import": "./dist/config.mjs", "types": "./dist/config.d.ts" }, + "./env": { + "import": "./dist/env.mjs", + "types": "./dist/env.d.ts" + }, "./pkgs": { "import": "./dist/pkgs.mjs", "types": "./dist/pkgs.d.ts" @@ -58,6 +50,9 @@ "types": "./dist/file-store.d.ts" } }, + "peerDependencies": { + "dotenv": "^16.4.7" + }, "dependencies": { "@kevisual/load": "^0.0.4" } diff --git a/rollup.config.mjs b/rollup.config.mjs deleted file mode 100644 index 2704af7..0000000 --- a/rollup.config.mjs +++ /dev/null @@ -1,94 +0,0 @@ -// rollup.config.js -import typescript from '@rollup/plugin-typescript'; -import resolve from '@rollup/plugin-node-resolve'; -import commonjs from '@rollup/plugin-commonjs'; -import { dts } from 'rollup-plugin-dts'; -/** - * @type {import('rollup').RollupOptions} - */ -export default [ - { - input: 'src/config.ts', // TypeScript 入口文件 - output: { - file: 'dist/config.mjs', // 输出文件 - format: 'es', // 输出格式设置为 ES 模块 - }, - plugins: [ - resolve(), // 使用 @rollup/plugin-node-resolve 解析 node_modules 中的模块 - commonjs(), - typescript(), // 使用 @rollup/plugin-typescript 处理 TypeScript 文件 - ], - external: [], - }, - { - input: 'src/config.ts', - output: { - file: 'dist/config.d.ts', - format: 'es', - }, - plugins: [dts()], - }, - { - input: 'src/pkgs.ts', // TypeScript 入口文件 - output: { - file: 'dist/pkgs.mjs', // 输出文件 - format: 'es', // 输出格式设置为 ES 模块 - }, - plugins: [ - resolve(), // 使用 @rollup/plugin-node-resolve 解析 node_modules 中的模块 - commonjs(), - typescript(), // 使用 @rollup/plugin-typescript 处理 TypeScript 文件 - ], - external: [], - }, - { - input: 'src/pkgs.ts', - output: { - file: 'dist/pkgs.d.ts', - format: 'es', - }, - plugins: [dts()], - }, - { - input: 'src/context.ts', // TypeScript 入口文件 - output: { - file: 'dist/context.mjs', // 输出文件 - format: 'es', // 输出格式设置为 ES 模块 - }, - plugins: [ - resolve(), // 使用 @rollup/plugin-node-resolve 解析 node_modules 中的模块 - commonjs(), - typescript(), // 使用 @rollup/plugin-typescript 处理 TypeScript 文件 - ], - external: [], - }, - { - input: 'src/context.ts', - output: { - file: 'dist/context.d.ts', - format: 'es', - }, - plugins: [dts()], - }, - { - input: 'src/file-store.ts', - output: { - file: 'dist/file-store.mjs', - format: 'es', - }, - plugins: [ - resolve(), - commonjs(), - typescript(), - ], - external: [], - }, - { - input: 'src/file-store.ts', - output: { - file: 'dist/file-store.d.ts', - format: 'es', - }, - plugins: [dts()], - } -]; diff --git a/src/config.ts b/src/config.ts index 9e3ebdc..e8d8075 100644 --- a/src/config.ts +++ b/src/config.ts @@ -104,6 +104,7 @@ export const init = (initConfigBase?: any): Config => { * @param initConfig 在全局未找到配置时,初始化配置的内容 * * @returns Config + * @deprecated 请使用 @kevisual/use-config/env 代替 1.0.15 版本删除 */ export const useConfig = (initConfig?: any): Config & T => { const config = (global as any).config; diff --git a/src/env.ts b/src/env.ts new file mode 100644 index 0000000..34ae457 --- /dev/null +++ b/src/env.ts @@ -0,0 +1,134 @@ +import fs from 'fs'; +import path from 'path'; +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; + }; + [key: string]: any; +}; +export const initConfig: Config = { + port: 3000, +}; +export const fileIsExist = (path: string) => { + try { + fs.accessSync(path, fs.constants.F_OK); + return true; + } catch (e) { + return false; + } +}; +export const getDirname = () => { + return process.cwd(); +}; +type ConfigOpts = { + envConfigFile?: string; + cwd?: string; + fileName?: string; +}; +/** + * 查找文件,3级查找。往上查询 + * @param fileName 文件名 + * @returns + */ +export const getConfigFile = (opts?: ConfigOpts) => { + if (opts?.envConfigFile) { + const filePath = path.join(opts.cwd || getDirname(), opts.envConfigFile); + if (fileIsExist(filePath)) { + return filePath; + } + } + const fileName = opts?.fileName || '.env'; + const dirname = opts?.cwd || getDirname(); + // 本级 + const benPath = dirname + '/' + fileName; + const ben = fileIsExist(benPath); + if (ben) return benPath; + // 上级 + const lastPath = path.join(dirname, '../' + fileName); + const last = fileIsExist(lastPath); + if (last) return lastPath; + // 上上级 + const lastLastPath = path.join(dirname, '../../' + fileName); + const lastLast = fileIsExist(lastLastPath); + if (lastLast) return lastLastPath; + return ''; +}; + +// 初始化读取配置文件 +export const init = (opts?: ConfigOpts & { dotenvOpts?: dotenv.DotenvConfigOptions }): Config => { + if (opts?.dotenvOpts) { + const prased = dotenv.config(opts.dotenvOpts).parsed as Config; + if (prased) { + return prased; + } else { + throw new Error('未找到配置文件'); + } + } + // 配置读取路径,3级判断 + const filePath = getConfigFile(opts); + console.log('config pathname:', filePath); + if (!filePath) { + throw new Error('未找到配置文件'); + } + const value = dotenv.config({ path: filePath }).parsed as Config; + return value; +}; + +/** + * 从全局获取 + * @param initConfig 在全局未找到配置时,初始化配置的内容 + * + * @returns Config + */ +export const useConfig = (): Config & T => { + const config = (global as any).config; + const _config = config || init(); + !config && ((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) { + v = process.env[key]; + } + if (!v) { + return opts?.defaultValue || null; + } + if (opts?.isNumber) { + return Number(v); + } + if (opts?.isBoolean) { + return v === 'true'; + } + return v; +}; diff --git a/src/test/env-get.ts b/src/test/env-get.ts new file mode 100644 index 0000000..1c580e5 --- /dev/null +++ b/src/test/env-get.ts @@ -0,0 +1,11 @@ +import { useConfig, useKey } from '../env.ts'; + +const config = useConfig(); + +console.log(config); + +const a = useKey('a'); + +console.log(a); + +console.log(process.env); diff --git a/tsconfig.json b/tsconfig.json index 918f972..02eb7ba 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,6 +29,5 @@ ], "exclude": [ "node_modules", - "rollup.config.js", ] } \ No newline at end of file diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..883b8e7 --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from 'tsup'; +// import glob from 'fast-glob'; +// const services = glob.sync('src/services/*.ts'); + +const entrys = ['src/index.ts', 'src/config.ts', 'src/pkgs.ts', 'src/context.ts', 'src/file-store.ts', 'src/env.ts']; + +export default defineConfig({ + entry: entrys, + outExtension: ({ format }) => ({ + js: format === 'esm' ? '.mjs' : '.js', + }), + splitting: false, + sourcemap: false, + clean: true, + format: 'esm', + external: ['dotenv'], + dts: true, + outDir: 'dist', + tsconfig: 'tsconfig.json', +});