UNPKG

@tys/vite-plugin-vue-page-route

Version:

A vite plugin for vue, auto generate route info by page

794 lines (776 loc) 27.5 kB
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw new Error('Dynamic require of "' + x + '" is not supported'); }); // src/context/index.ts import chokidar from "chokidar"; // src/shared/constant.ts var PAGE_DIR = "src/views"; var PAGE_GLOB = ["**/index.{vue,tsx,jsx}", "!**/components/**"]; var ROUTE_DTS = "src/typings/page-route.d.ts"; var ROUTE_MODULE_DIR = "src/router/modules"; var ROUTE_MODULE_EXT = "ts"; var ROUTE_MODULE_TYPE = "AuthRoute.Route"; var ROOT_ROUTE = "root"; var NOT_FOUND_ROUTE = "not-found"; var PAGE_DEGREE_SPLIT_MARK = "_"; var SPLASH_MARK = "/"; var ROUTE_NAME_REG = /^([a-zA-Z]|\$|_|\d|-)+$/; var INVALID_ROUTE_NAME = "invalid-route-name"; var CAMEL_OR_PASCAL = /[A-Z]/; // src/shared/option.ts function createPluginOptions(userOptions, rootDir) { const IGNORE_UNDERLINE_REG = /^_([a-zA-Z]|[0-9]|$)+_*/; const BUILTIN_ROUTE_MODULE = "_builtin"; const options = { pageDir: PAGE_DIR, pageGlobs: PAGE_GLOB, routeDts: ROUTE_DTS, routeModuleDir: ROUTE_MODULE_DIR, routeModuleExt: ROUTE_MODULE_EXT, routeModuleType: ROUTE_MODULE_TYPE, routeNameTansformer: (name) => name.replace(IGNORE_UNDERLINE_REG, ""), lazyImport: () => true, onRouteModuleGenerate: (name) => !name.includes(BUILTIN_ROUTE_MODULE), rootDir }; Object.assign(options, userOptions); return options; } // src/shared/glob.ts import fastGlob from "fast-glob"; import { isMatch } from "micromatch"; function getGlobsOfPage(pageGlobs, pageDir) { const globs = fastGlob.sync(pageGlobs, { onlyFiles: true, cwd: pageDir }); return globs.sort(); } function getRelativePathOfGlob(glob, pageDir) { return `${pageDir}/${glob}`; } function matchGlob(glob, options) { const isFile = isMatch(glob, "**/*.*"); const { pageGlobs } = options; const patterns = isFile ? pageGlobs : pageGlobs.filter((pattern) => !pattern.includes(".")); return patterns.every((pattern) => isMatch(glob, pattern)); } // src/shared/route.ts import { writeFile, remove } from "fs-extra"; import { access } from "fs/promises"; import { red, bgRed, green, bgYellow, yellow } from "kolorist"; import { transformFile } from "@swc/core"; function transformRouteName(glob, routeName, pageDir) { let name = routeName; const filePath = getRelativePathOfGlob(glob, pageDir); if (CAMEL_OR_PASCAL.test(routeName)) { let warning = `${bgYellow("RECOMMEND")} `; warning += yellow(`the filePath: ${filePath}`); warning += green(` it's recommended to use kebab-case name style`); warning += green(` example: good: user-info bad: userInfo, UserInfo`); console.info(warning); } if (!ROUTE_NAME_REG.test(name)) { name = INVALID_ROUTE_NAME; let error = `${bgRed("ERROR")} `; error += red(`the path is invalid: ${filePath} ! `); error += red(`routeName: ${routeName} !`); error += green( ` the directory name and file name can only include letter[a-zA-Z], number[0-9], underline[_] and dollar[$]` ); console.error(error); } return name; } function getRouteNameByGlob(glob, pageDir) { const globSplits = glob.split(SPLASH_MARK); const isFile = glob.includes("."); const sliceLength = isFile ? globSplits.length - 1 : globSplits.length; const routeName = globSplits.splice(0, sliceLength).join(PAGE_DEGREE_SPLIT_MARK); return transformRouteName(glob, routeName, pageDir); } function getAllRouteNames(routeName) { const names = routeName.split(PAGE_DEGREE_SPLIT_MARK); const namesWithParent = []; for (let i = 1; i <= names.length; i += 1) { const parentName = names.slice(0, i).reduce((pre, cur) => pre + PAGE_DEGREE_SPLIT_MARK + cur); namesWithParent.push(parentName); } return namesWithParent; } function getRouteFilePathByGlob(glob) { return `./${glob}`; } function getRouteNameByGlobWithTransformer(glob, options) { const routeName = getRouteNameByGlob(glob, options.pageDir); return options.routeNameTansformer(routeName); } function getRouteConfigByGlobs(globs, options) { const config = { names: [], files: [] }; globs.sort().forEach((glob) => { const routeName = getRouteNameByGlob(glob, options.pageDir); const names = getAllRouteNames(routeName); config.names.push(...names); const filePath = getRouteFilePathByGlob(glob); config.files.push({ name: routeName, path: filePath }); }); config.names = Array.from(/* @__PURE__ */ new Set([...config.names])).map((name) => options.routeNameTansformer(name)).filter((name) => Boolean(name) && name !== INVALID_ROUTE_NAME); config.files = config.files.map(({ name, path }) => ({ name: options.routeNameTansformer(name), path })).filter((item) => item.name !== INVALID_ROUTE_NAME); return config; } function getRouteModuleConfig(index, length) { const actions = [ [length === 1, { component: "self", hasSingleLayout: true }], [length === 2 && index === 0, { component: "basic", hasSingleLayout: false }], [length === 2 && index === 1, { component: "self", hasSingleLayout: false }], [length >= 3 && index === 0, { component: "basic", hasSingleLayout: false }], [length >= 3 && index === length - 1, { component: "self", hasSingleLayout: false }], [true, { component: "multi", hasSingleLayout: false }] ]; const config = { component: "self", hasSingleLayout: false }; const findItem = actions.find(([condition]) => condition); return findItem?.[1] || config; } function getRoutePathFromName(routeName) { const PATH_SPLIT_MARK = "/"; return PATH_SPLIT_MARK + routeName.replace(new RegExp(`${PAGE_DEGREE_SPLIT_MARK}`, "g"), PATH_SPLIT_MARK); } function getRouteModuleNameByRouteName(routeName) { const routeNames = getAllRouteNames(routeName); if (!routeNames.length) { throw new Error(`\u8DEF\u7531\u540D\u79F0\u4E0D\u6B63\u786E!`); } return routeNames[0]; } function getRouteModuleNameByGlob(glob, options) { const routeName = getRouteNameByGlobWithTransformer(glob, options); const moduleName = getRouteModuleNameByRouteName(routeName); return moduleName; } function checkIsValidRouteModule(data) { const isObject = Object.prototype.toString.call(data) === "[object Object]"; return isObject && data.name && data.path && data.component && data.meta; } function getSingleRouteModulesFromRouteName(routeName) { const routeNames = getAllRouteNames(routeName); const modules = routeNames.map((item, index) => { const config = getRouteModuleConfig(index, routeNames.length); const module = { name: item, path: getRoutePathFromName(item), component: config.component, meta: { title: item, icon: "mdi:menu" } }; if (config.hasSingleLayout) { module.meta.singleLayout = "basic"; } return module; }); return modules; } function getSingleRouteModulesFromGlob(glob, options) { const routeName = getRouteNameByGlobWithTransformer(glob, options); const modules = getSingleRouteModulesFromRouteName(routeName); return modules; } function getSingleRouteModulesWithChildren(singleModules) { const reversedModules = [...singleModules].reverse(); reversedModules.forEach((module, index) => { if (index < reversedModules.length - 1) { reversedModules[index + 1].children = [module]; } }); return reversedModules[reversedModules.length - 1] || null; } function recurseMergeModule(modules, singleModules, singleRouteLevel) { if (!singleModules.length) return; const currentLevelRouteModule = singleModules[singleRouteLevel]; const findIndex = modules.findIndex((module) => module.name === currentLevelRouteModule.name); if (findIndex > -1) { const findModule = modules[findIndex]; if (!findModule.children) { findModule.children = []; } recurseMergeModule(findModule.children, singleModules, singleRouteLevel + 1); } else { const pushModule = getSingleRouteModulesWithChildren(singleModules.slice(singleRouteLevel)); if (pushModule) { modules.push(pushModule); } } } function mergeFirstDegreeRouteModule(firstDegreeRouteModule, singleModules) { if (!firstDegreeRouteModule.children) { firstDegreeRouteModule.children = []; } recurseMergeModule(firstDegreeRouteModule.children, singleModules, 1); } function getTotalRouteModuleFromNames(routeNames) { let module; routeNames.forEach((routeName, index) => { const modules = getSingleRouteModulesFromRouteName(routeName); const [firstModule] = modules; if (index === 0) { module = firstModule; } if (firstModule.name === module.name && modules.length > 1) { mergeFirstDegreeRouteModule(module, modules); } }); return module; } function getRouteModuleFilePath(moduleName, options) { const { rootDir, routeModuleDir, routeModuleExt } = options; const filePath = `${rootDir}/${routeModuleDir}/${moduleName}.${routeModuleExt}`; return filePath; } async function getIsRouteModuleFileExist(moduleName, options) { const filePath = getRouteModuleFilePath(moduleName, options); let exist = false; try { await access(filePath); exist = true; } catch { } return { exist, filePath }; } function getTheSmallLengthOfStrArr(arr) { let name = arr[0]; arr.forEach((item) => { if (name === null) { name = item; } else { name = item.length < name.length ? item : name; } }); return name; } async function getRouteModuleWhetherFileExist(params) { const { moduleName, existModuleName, routeConfig, options, existCallback } = params; const { exist, filePath } = await getIsRouteModuleFileExist(existModuleName, options); let module; try { if (exist) { const importModule = await getRouteModuleFromFile(filePath, existModuleName, options); if (checkIsValidRouteModule(importModule)) { module = await existCallback(importModule, filePath); } else { throw Error("invalid route module!"); } } else { throw Error("not exist module file!"); } } catch (error) { const routeNames = routeConfig.files.filter((item) => item.name.includes(moduleName)).map((item) => item.name); module = getTotalRouteModuleFromNames(routeNames); } return module; } function recurseRemoveModuleByName(module, routeName) { if (!module.children) return; module.children = module.children.filter((item) => item.name !== routeName); module.children.forEach((item) => { if (routeName.includes(item.name)) { recurseRemoveModuleByName(item, routeName); } }); } function recurseRemoveModuleByNames(module, routeNames) { if (!routeNames.length) return; routeNames.forEach((item) => { recurseRemoveModuleByName(module, item); }); } function getRenamedDirConfig(dispatchs, options) { const unlinkDirs = []; const addDirs = []; dispatchs.forEach((dispatch) => { if (dispatch.event === "unlinkDir") { unlinkDirs.push(dispatch.path); } if (dispatch.event === "addDir") { addDirs.push(dispatch.path); } }); const oldDir = getTheSmallLengthOfStrArr(unlinkDirs); const newDir = getTheSmallLengthOfStrArr(addDirs); const oldRouteName = getRouteNameByGlobWithTransformer(oldDir, options); const oldRouteFilePath = getRouteFilePathByGlob(oldDir); const newRouteName = getRouteNameByGlobWithTransformer(newDir, options); const newRouteFilePath = getRouteFilePathByGlob(newDir); return { oldRouteName, newRouteName, oldRouteFilePath, newRouteFilePath }; } function getDelDirConfig(dispatchs, options) { const unlinkDirs = []; dispatchs.forEach((dispatch) => { if (dispatch.event === "unlinkDir") { unlinkDirs.push(dispatch.path); } }); const delDir = getTheSmallLengthOfStrArr(unlinkDirs); const delRouteName = getRouteNameByGlobWithTransformer(delDir, options); return { delRouteName }; } function getAddDirConfig(dispatchs, options) { const globs = []; dispatchs.forEach((dispatch) => { if (dispatch.event === "add") { globs.push(dispatch.path); } }); const config = getRouteConfigByGlobs(globs, options); return config; } function getDelFileConfig(dispatchs, options) { const delRouteNames = []; dispatchs.forEach((dispatch) => { if (dispatch.event === "unlink") { const name = getRouteNameByGlobWithTransformer(dispatch.path, options); delRouteNames.push(name); } }); return { delRouteNames }; } function getAddFileConfig(dispatchs, options) { const addRouteNames = []; const addRouteFiles = []; dispatchs.forEach((dispatch) => { if (dispatch.event === "add") { const name = getRouteNameByGlobWithTransformer(dispatch.path, options); addRouteNames.push(name); const path = getRouteFilePathByGlob(dispatch.path); addRouteFiles.push({ name, path }); } }); const config = { names: addRouteNames, files: addRouteFiles }; return config; } async function getRouteModuleFromFile(filePath, moduleName, options) { const transformedFilePath = filePath.replace(`${moduleName}.${options.routeModuleExt}`, `${moduleName}-swc.js`); const { code } = await transformFile(filePath, { filename: transformedFilePath, module: { type: "commonjs" } }); if (code) { await writeFile(transformedFilePath, code, "utf-8"); } const { default: importModule } = __require(transformedFilePath); await remove(transformedFilePath); return importModule; } function transformModuleNameToVariable(name) { return name.replace(/-(\w)/g, (_, match) => match.toUpperCase()); } // src/shared/eslint.ts import { access as access2 } from "fs/promises"; import execa from "execa"; async function handleEslintFormat(filePath) { const eslintBinPath = `${process.cwd()}/node_modules/eslint/bin/eslint.js`; try { await access2(eslintBinPath); await execa("node", [eslintBinPath, filePath, "--fix"]); } catch { } } // src/context/declaration.ts import { writeFile as writeFile2 } from "fs/promises"; function getDeclarationCode(routeConfig) { let code = `declare namespace PageRoute { /** * the root route key * @translate \u6839\u8DEF\u7531 */ type RootRouteKey = '${ROOT_ROUTE}'; /** * the not found route, which catch the invalid route path * @translate \u672A\u627E\u5230\u8DEF\u7531(\u6355\u83B7\u65E0\u6548\u8DEF\u5F84\u7684\u8DEF\u7531) */ type NotFoundRouteKey = '${NOT_FOUND_ROUTE}'; /** * the route key * @translate \u9875\u9762\u8DEF\u7531 */ type RouteKey =`; routeConfig.names.forEach((name) => { code += ` | '${name}'`; }); code += `; /** * last degree route key, which has the page file * @translate \u6700\u540E\u4E00\u7EA7\u8DEF\u7531(\u8BE5\u7EA7\u8DEF\u6709\u5BF9\u5E94\u7684\u9875\u9762\u6587\u4EF6) */ type LastDegreeRouteKey = Extract< RouteKey,`; routeConfig.files.forEach((item) => { code += ` | '${item.name}'`; }); code += ` >; } `; return code; } async function generateDeclaration(routeConfig, options) { const code = getDeclarationCode(routeConfig); const filePath = `${options.rootDir}/${options.routeDts}`; await writeFile2(filePath, code, "utf-8"); await handleEslintFormat(filePath); } // src/context/views.ts import { writeFile as writeFile3 } from "fs/promises"; function transformKey(key) { return key.includes("-") ? `'${key}'` : key; } function isPureNumberKey(key) { const NUM_REG = /^\d+$/; return NUM_REG.test(key); } function transformImportKey(key) { const tranform = isPureNumberKey(key) ? `_view_${key}` : key; return tranform; } function getViewsCode(routeFiles, options) { let preCode = `import type { RouteComponent } from 'vue-router'; `; let code = ` export const views: Record< PageRoute.LastDegreeRouteKey, RouteComponent | (() => Promise<{ default: RouteComponent }>) > = {`; routeFiles.forEach(({ name, path }, index) => { const isLazy = options.lazyImport(name); const key = transformKey(name); if (isLazy) { code += ` ${key}: () => import('${path}')`; } else { const importKey = transformImportKey(name); preCode += `import ${importKey} from '${path}'; `; if (key === path && !isPureNumberKey(name)) { code += ` ${key}`; } else { code += ` ${key}: ${importKey}`; } } if (index < routeFiles.length - 1) { code += ","; } }); code += "\n};\n"; return preCode + code; } async function generateViews(routeFiles, options) { const code = getViewsCode(routeFiles, options); const filePath = `${options.rootDir}/${options.pageDir}/index.ts`; await writeFile3(filePath, code, "utf-8"); await handleEslintFormat(filePath); } // src/context/fs.ts import { remove as remove2 } from "fs-extra"; // src/context/module.ts import { ensureFile, writeFile as writeFile4 } from "fs-extra"; async function generateRouteModuleCode(moduleName, module, options) { if (moduleName === INVALID_ROUTE_NAME) return; const filePath = getRouteModuleFilePath(moduleName, options); const variable = transformModuleNameToVariable(moduleName); const code = `const ${variable}: ${options.routeModuleType} = ${JSON.stringify( module )}; export default ${variable};`; await ensureFile(filePath); await writeFile4(filePath, code, "utf-8"); await handleEslintFormat(filePath); } // src/context/fs.ts async function fileWatcherHandler(dispatchs, hooks) { const dispatchWithCategory = { addDir: [], unlinkDir: [], add: [], unlink: [] }; dispatchs.forEach((item) => { dispatchWithCategory[item.event].push(item.path); }); const hasAddDir = dispatchWithCategory.addDir.length > 0; const hasUnlinkDir = dispatchWithCategory.unlinkDir.length > 0; const hasAdd = dispatchWithCategory.add.length > 0; const hasUnlink = dispatchWithCategory.unlink.length > 0; const { onRenameDirWithFile, onDelDirWithFile, onAddDirWithFile, onDelFile, onAddFile } = hooks; const conditions = [ [hasAddDir && hasUnlinkDir && hasAdd && hasUnlink, onRenameDirWithFile], [hasUnlinkDir && hasUnlink, onDelDirWithFile], [hasAddDir && hasAdd, onAddDirWithFile], [hasUnlink, onDelFile], [hasAdd, onAddFile] ]; const [, callback] = conditions.find(([condition]) => condition) || [true, async () => { }]; await callback(); } function createFWHooksOfGenDeclarationAndViews(dispatchs, routeConfig, options) { const hooks = { async onRenameDirWithFile() { const { oldRouteName, newRouteName, oldRouteFilePath, newRouteFilePath } = getRenamedDirConfig( dispatchs, options ); routeConfig.names = routeConfig.names.map((name) => name.replace(oldRouteName, newRouteName)); routeConfig.files = routeConfig.files.map((item) => { const name = item.name.replace(oldRouteName, newRouteName); const path = item.path.replace(oldRouteFilePath, newRouteFilePath); return { name, path }; }); }, async onDelDirWithFile() { const { delRouteName } = getDelDirConfig(dispatchs, options); routeConfig.names = routeConfig.names.filter((name) => !name.includes(delRouteName)); routeConfig.files = routeConfig.files.filter((item) => !item.name.includes(delRouteName)); }, async onAddDirWithFile() { const config = getAddDirConfig(dispatchs, options); routeConfig.names = routeConfig.names.concat(config.names).sort(); routeConfig.files = routeConfig.files.concat(config.files).sort((a, b) => a.name > b.name ? 1 : -1); }, async onDelFile() { const { delRouteNames } = getDelFileConfig(dispatchs, options); routeConfig.names = routeConfig.names.filter((name) => delRouteNames.every((item) => !name.includes(item))); routeConfig.files = routeConfig.files.filter((item) => delRouteNames.every((v) => !item.name.includes(v))); }, async onAddFile() { const config = getAddFileConfig(dispatchs, options); routeConfig.names = routeConfig.names.concat(config.names).sort(); routeConfig.files = routeConfig.files.concat(config.files).sort((a, b) => a.name > b.name ? 1 : -1); } }; return hooks; } function createFWHooksOfGenModule(dispatchs, routeConfig, options) { async function getRouteModule(moduleName, existModuleName, existCallback) { return getRouteModuleWhetherFileExist({ moduleName, existModuleName, routeConfig, options, existCallback }); } const hooks = { async onRenameDirWithFile() { const { oldRouteName, newRouteName } = getRenamedDirConfig(dispatchs, options); if (!oldRouteName || !newRouteName) return; const oldRoutePath = getRoutePathFromName(oldRouteName); const newRoutePath = getRoutePathFromName(newRouteName); const oldModuleName = getRouteModuleNameByRouteName(oldRouteName); const newModuleName = getRouteModuleNameByRouteName(newRouteName); const module = await getRouteModule(newModuleName, oldModuleName, async (routeModule, filePath) => { const moduleJson = JSON.stringify(routeModule); const updateModuleJson = moduleJson.replace(new RegExp(`"${oldRouteName}`, "g"), `"${newRouteName}`).replace(new RegExp(`${oldRoutePath}`, "g"), newRoutePath); const existModule = JSON.parse(updateModuleJson); await remove2(filePath); return existModule; }); if (module) { await generateRouteModuleCode(newModuleName, module, options); } }, async onDelDirWithFile() { const { delRouteName } = getDelDirConfig(dispatchs, options); const moduleName = getRouteModuleNameByRouteName(delRouteName); const globs = dispatchs.filter((dispatch) => dispatch.event === "unlink").map((dispatch) => dispatch.path); const routeNames = globs.map((glob) => getRouteNameByGlobWithTransformer(glob, options)); const module = await getRouteModule(moduleName, moduleName, async (routeModule, filePath) => { if (delRouteName === moduleName) { await remove2(filePath); return null; } recurseRemoveModuleByNames(routeModule, routeNames); return routeModule; }); if (module) { await generateRouteModuleCode(moduleName, module, options); } }, async onAddDirWithFile() { const globs = dispatchs.filter((dispatch) => dispatch.event === "add").map((dispatch) => dispatch.path); const moduleName = getRouteModuleNameByGlob(globs[0], options); const module = await getRouteModule(moduleName, moduleName, async (routeModule) => { globs.forEach((glob) => { const modules = getSingleRouteModulesFromGlob(glob, options); mergeFirstDegreeRouteModule(routeModule, modules); }); return routeModule; }); if (module) { await generateRouteModuleCode(moduleName, module, options); } }, async onDelFile() { const { delRouteNames } = getDelFileConfig(dispatchs, options); const globs = dispatchs.filter((dispatch) => dispatch.event === "unlink").map((dispatch) => dispatch.path); delRouteNames.forEach(async (delRouteName) => { const moduleName = getRouteModuleNameByRouteName(delRouteName); const routeNames = globs.map((glob) => getRouteNameByGlobWithTransformer(glob, options)); const module = await getRouteModule(moduleName, moduleName, async (routeModule, filePath) => { if (delRouteName === moduleName) { await remove2(filePath); return null; } recurseRemoveModuleByNames(routeModule, routeNames); return routeModule; }); if (module) { await generateRouteModuleCode(moduleName, module, options); } }); }, async onAddFile() { await this.onAddDirWithFile(); } }; return hooks; } // src/context/index.ts var Context = class { options; routeConfig; dispatchId = null; dispatchStack = []; constructor(options = {}) { const rootDir = process.cwd(); this.options = createPluginOptions(options, rootDir); const globs = getGlobsOfPage(this.options.pageGlobs, this.options.pageDir); this.routeConfig = getRouteConfigByGlobs(globs, this.options); this.generate(); } async generate() { await generateDeclaration(this.routeConfig, this.options); await generateViews(this.routeConfig.files, this.options); } createFileWatcherHooks(dispatchs) { const declarationAndViewsHooks = createFWHooksOfGenDeclarationAndViews(dispatchs, this.routeConfig, this.options); const filteredDispatchs = dispatchs.filter((dispatch) => { const isFile = dispatch.event === "add" || dispatch.event === "unlink"; if (!isFile) return true; const routeName = getRouteNameByGlob(dispatch.path, this.options.pageDir); const generateRouteModule = this.options.onRouteModuleGenerate(routeName); return generateRouteModule; }); const moduleHooks = createFWHooksOfGenModule(filteredDispatchs, this.routeConfig, this.options); const hooks = { async onRenameDirWithFile() { await declarationAndViewsHooks.onRenameDirWithFile(); await moduleHooks.onRenameDirWithFile(); }, async onDelDirWithFile() { await declarationAndViewsHooks.onDelDirWithFile(); await moduleHooks.onDelDirWithFile(); }, async onAddDirWithFile() { await declarationAndViewsHooks.onAddDirWithFile(); await moduleHooks.onAddDirWithFile(); }, async onDelFile() { await declarationAndViewsHooks.onDelFile(); await moduleHooks.onDelFile(); }, async onAddFile() { await declarationAndViewsHooks.onAddFile(); await moduleHooks.onAddFile(); } }; return hooks; } dispatchFileWatcher(glob, event) { const isMatch2 = matchGlob(glob, this.options); if (!isMatch2) return; const dispacth = { event, path: glob }; if (this.checkDispatch(dispacth)) { this.dispatchStack.push(dispacth); } if (!this.dispatchId) { this.dispatchId = setTimeout(async () => { const hooks = this.createFileWatcherHooks(this.dispatchStack); await fileWatcherHandler(this.dispatchStack, hooks); this.generate(); this.dispatchStack = []; this.dispatchId = null; }, 100); } } checkDispatch(dispatch) { const isFile = dispatch.event === "add" || dispatch.event === "unlink"; if (!isFile) return true; const routeName = getRouteNameByGlob(dispatch.path, this.options.pageDir); return routeName !== INVALID_ROUTE_NAME; } setupFileWatcher() { const events = ["addDir", "unlinkDir", "add", "unlink"]; events.forEach((event) => { chokidar.watch(["."], { ignoreInitial: true, cwd: this.options.pageDir }).on(event, (path) => { this.dispatchFileWatcher(path, event); }); }); } }; // src/index.ts function pageRoute(options) { const context = new Context(options); const plugin = { name: "vite-plugin-vue-page-route", enforce: "post", configureServer() { context.setupFileWatcher(); } }; return plugin; } var src_default = pageRoute; export { src_default as default };