Kirk Lin
2023-10-08 a712a8e5a088da59b32343eb23819ea9040830ef
internal/vite-config/src/plugins/appConfig.ts
@@ -1,104 +1,21 @@
import colors from 'picocolors';
import { readPackageJSON } from 'pkg-types';
import GenerateConfig from 'unplugin-config/vite';
import { type PluginOption } from 'vite';
import { getEnvConfig } from '../utils/env';
import { createContentHash } from '../utils/hash';
import { strToHex } from '../utils/hash';
const GLOBAL_CONFIG_FILE_NAME = '_app.config.js';
const PLUGIN_NAME = 'app-config';
async function createAppConfigPlugin({
  root,
  isBuild,
}: {
  root: string;
  isBuild: boolean;
}): Promise<PluginOption> {
  let publicPath: string;
  let source: string;
  if (!isBuild) {
    return {
      name: PLUGIN_NAME,
    };
  }
  const { version = '' } = await readPackageJSON(root);
  return {
    name: PLUGIN_NAME,
    async configResolved(_config) {
      const appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? '';
      // appTitle = appTitle.replace(/\s/g, '_').replace(/-/g, '_');
      publicPath = _config.base;
      source = await getConfigSource(appTitle);
    },
    async transformIndexHtml(html) {
      publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`;
      const appConfigSrc = `${
        publicPath || '/'
      }${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}`;
      return {
        html,
        tags: [
          {
            tag: 'script',
            attrs: {
              src: appConfigSrc,
            },
          },
        ],
      };
    },
    async generateBundle() {
      try {
        this.emitFile({
          type: 'asset',
          fileName: GLOBAL_CONFIG_FILE_NAME,
          source,
        });
        console.log(colors.cyan(`✨configuration file is build successfully!`));
      } catch (error) {
        console.log(
          colors.red('configuration file configuration file failed to package:\n' + error),
        );
      }
    },
  };
// This constant sets the output directory for the Vite package
const OUTPUT_DIR = 'dist';
const config: any = getEnvConfig().then();
const APP_NAME = strToHex(config?.VITE_GLOB_APP_TITLE ?? 'Vben Admin');
export function createConfigPluginConfig(shouldGenerateConfig: boolean): PluginOption {
  // https://github.com/kirklin/unplugin-config
  return GenerateConfig({
    disabledConfig: !shouldGenerateConfig,
    globConfigFileName: GLOBAL_CONFIG_FILE_NAME,
    outputDir: OUTPUT_DIR,
    appName: APP_NAME,
    envConfigPrefix: 'VITE_GLOB_',
  });
}
/**
 * Get the configuration file variable name
 * @param env
 */
const getVariableName = (title: string) => {
  function strToHex(str: string) {
    const result: string[] = [];
    for (let i = 0; i < str.length; ++i) {
      const hex = str.charCodeAt(i).toString(16);
      result.push(('000' + hex).slice(-4));
    }
    return result.join('').toUpperCase();
  }
  return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, '');
};
async function getConfigSource(appTitle: string) {
  const config = await getEnvConfig();
  const variableName = getVariableName(appTitle);
  const windowVariable = `window.${variableName}`;
  // Ensure that the variable will not be modified
  let source = `${windowVariable}=${JSON.stringify(config)};`;
  source += `
    Object.freeze(${windowVariable});
    Object.defineProperty(window, "${variableName}", {
      configurable: false,
      writable: false,
    });
  `.replace(/\s/g, '');
  return source;
}
export { createAppConfigPlugin };