env.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import type { ApplicationPluginOptions } from '../typing';
  2. import { existsSync } from 'node:fs';
  3. import { join } from 'node:path';
  4. import { fs } from '@vben/node-utils';
  5. import dotenv from 'dotenv';
  6. const getBoolean = (value: string | undefined) => value === 'true';
  7. const getString = (value: string | undefined, fallback: string) =>
  8. value ?? fallback;
  9. const getNumber = (value: string | undefined, fallback: number) =>
  10. Number(value) || fallback;
  11. /**
  12. * 获取当前环境下生效的配置文件名
  13. */
  14. function getConfFiles() {
  15. const script = process.env.npm_lifecycle_script as string;
  16. const reg = /--mode ([\d_a-z]+)/;
  17. const result = reg.exec(script);
  18. let mode = 'production';
  19. if (result) {
  20. mode = result[1] as string;
  21. }
  22. return ['.env', '.env.local', `.env.${mode}`, `.env.${mode}.local`];
  23. }
  24. /**
  25. * Get the environment variables starting with the specified prefix
  26. * @param match prefix
  27. * @param confFiles ext
  28. */
  29. async function loadEnv<T = Record<string, string>>(
  30. match = 'VITE_GLOB_',
  31. confFiles = getConfFiles(),
  32. ) {
  33. let envConfig = {};
  34. for (const confFile of confFiles) {
  35. try {
  36. const confFilePath = join(process.cwd(), confFile);
  37. if (existsSync(confFilePath)) {
  38. const envPath = await fs.readFile(confFilePath, {
  39. encoding: 'utf8',
  40. });
  41. const env = dotenv.parse(envPath);
  42. envConfig = { ...envConfig, ...env };
  43. }
  44. } catch (error) {
  45. console.error(`Error while parsing ${confFile}`, error);
  46. }
  47. }
  48. const reg = new RegExp(`^(${match})`);
  49. Object.keys(envConfig).forEach((key) => {
  50. if (!reg.test(key)) {
  51. Reflect.deleteProperty(envConfig, key);
  52. }
  53. });
  54. return envConfig as T;
  55. }
  56. async function loadAndConvertEnv(
  57. match = 'VITE_',
  58. confFiles = getConfFiles(),
  59. ): Promise<
  60. {
  61. appTitle: string;
  62. base: string;
  63. port: number;
  64. } & Partial<ApplicationPluginOptions>
  65. > {
  66. const envConfig = await loadEnv(match, confFiles);
  67. const {
  68. VITE_APP_TITLE,
  69. VITE_ARCHIVER,
  70. VITE_BASE,
  71. VITE_COMPRESS,
  72. VITE_DEVTOOLS,
  73. VITE_INJECT_APP_LOADING,
  74. VITE_NITRO_MOCK,
  75. VITE_PORT,
  76. VITE_PWA,
  77. VITE_VISUALIZER,
  78. } = envConfig;
  79. const compressTypes = (VITE_COMPRESS ?? '')
  80. .split(',')
  81. .filter((item) => item === 'brotli' || item === 'gzip');
  82. return {
  83. appTitle: getString(VITE_APP_TITLE, 'Velofex'),
  84. archiver: getBoolean(VITE_ARCHIVER),
  85. base: getString(VITE_BASE, '/'),
  86. compress: compressTypes.length > 0,
  87. compressTypes,
  88. devtools: getBoolean(VITE_DEVTOOLS),
  89. injectAppLoading: getBoolean(VITE_INJECT_APP_LOADING),
  90. nitroMock: getBoolean(VITE_NITRO_MOCK),
  91. port: getNumber(VITE_PORT, 5173),
  92. pwa: getBoolean(VITE_PWA),
  93. visualizer: getBoolean(VITE_VISUALIZER),
  94. };
  95. }
  96. export { loadAndConvertEnv, loadEnv };