gen-router 自动生成路由

134 阅读1分钟
const path = require('path');
const fs = require('fs');
const childProcess = require('child_process');
const pagesJson = require('./src/pages.json');

const workDir = 'src';
const workPath = path.join(__dirname, workDir);
const configPath = path.join(workPath, 'config');
const workAllFiles = fs.readdirSync(workPath);

main();

function main() {
  syncPagesJson();
  syncRouters();
}

function syncRouters() {
  const pagesDir = workAllFiles.filter((name) => name.includes('pages') && fs.statSync(path.join(workPath, name)).isDirectory());
  const fileNamePathMap = {};
  function setFileNamePathMap(files) {
    files.forEach((fileName) => {
      const filePath = path.join(workPath, fileName);
      if (fs.statSync(filePath).isDirectory() && !fileName.endsWith('components')) {
        setFileNamePathMap(fs.readdirSync(filePath).map((item) => `${fileName}/${item}`));
      } else if (fs.statSync(filePath).isFile() && fileName.endsWith('.vue')) {
        const baseName = path.basename(filePath);
        const dirNames = path.dirname(filePath).split(path.sep);
        fileNamePathMap[baseName === 'index.vue' ? dirNames[dirNames.length - 1] : baseName.substring(0, baseName.length - 4)] = `/${fileName.substring(0, fileName.length - 4)}`;
      }
    });
  }
  setFileNamePathMap(pagesDir);
  const configExists = fs.existsSync(configPath);
  if (!configExists) {
    fs.mkdirSync(configPath);
  }
  fs.writeFileSync(path.join(configPath, 'routers.js'), `export default ${JSON.stringify(fileNamePathMap, null, 2)}`);
  childProcess.execSync('npx eslint src/config/routers.js --fix');
}

function syncPagesJson() {
  pagesJson.pages = genPages(true, 'pages', path.join(workPath, 'pages'), pagesJson.pages);
  pagesJson.subPackages = genSubPackages();
  fs.writeFileSync(path.join(workPath, 'pages.json'), `${JSON.stringify(pagesJson, null, 2)}`);
}

function genPages(isPages, pagesDirName, pagesDirPath, pages = []) {
  const realPagesList = [];
  const pagesChildDirs = fs.readdirSync(pagesDirPath)
    .filter((name) => fs.statSync(path.join(pagesDirPath, name)).isDirectory());
  pagesChildDirs.forEach((dir) => {
    const files = fs.readdirSync(path.join(pagesDirPath, dir)).filter((name) => name.endsWith('.vue'));
    files.forEach((name) => {
      const basename = path.basename(name, '.vue');
      realPagesList.push({
        path: isPages ? `${pagesDirName}/${dir}/${basename}` : `${dir}/${basename}`,
        style: {
          navigationBarTitleText: basename === 'index' ? dir : basename,
        },
      });
    });
  });
  const realPagesListPaths = realPagesList.map((item) => item.path);
  const filterPages = pages.filter((item) => realPagesListPaths.includes(item.path));
  const pagePaths = filterPages.map((page) => page.path);
  const addPagesList = realPagesList.filter((item) => !pagePaths.includes(item.path));
  return [...filterPages, ...addPagesList];
}

function genSubPackages() {
  const subPackagesDirs = workAllFiles.filter((item) => /^pages\w+/.test(item) && fs.statSync(path.join(workPath, item)).isDirectory());
  let { subPackages } = pagesJson;
  subPackages = subPackages.filter((subPackage) => subPackagesDirs.includes(subPackage.root));
  subPackages.forEach((subPackage) => {
    subPackage.pages = genPages(false,
      subPackage.root, path.join(workPath, subPackage.root), subPackage.pages);
  });
  const subPackagesRoots = subPackages.map((subPackage) => subPackage.root);
  const addSubPackagesDirs = subPackagesDirs
    .filter((subPackageDir) => !subPackagesRoots.includes(subPackageDir));
  const addSubPackages = addSubPackagesDirs.map((subPackageDir) => ({
    root: subPackageDir,
    pages: genPages(false, subPackageDir, path.join(workPath, subPackageDir)),
  }));
  return [...subPackages, ...addSubPackages];
}