vitarx-router 4.0.0-beta.2 → 4.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -17
- package/dist/{plugin-vite/auto-routes → auto-routes}/handleHotUpdate.d.ts +1 -1
- package/dist/components/RouterView.js +5 -4
- package/dist/core/common/constant.d.ts +5 -6
- package/dist/core/common/constant.js +5 -6
- package/dist/core/common/utils.js +2 -1
- package/dist/core/router/checkOptions.d.ts +11 -0
- package/dist/core/router/checkOptions.js +119 -0
- package/dist/core/router/manager.js +27 -23
- package/dist/core/router/router.d.ts +154 -1
- package/dist/core/router/router.js +303 -230
- package/dist/core/router/web.d.ts +13 -0
- package/dist/core/router/web.js +35 -4
- package/dist/core/shared/link.d.ts +7 -0
- package/dist/core/shared/link.js +11 -8
- package/dist/core/shared/route.js +1 -2
- package/dist/core/shared/router.d.ts +3 -3
- package/dist/core/shared/router.js +7 -4
- package/dist/core/types/options.d.ts +2 -0
- package/dist/file-router/config/index.d.ts +2 -1
- package/dist/file-router/config/index.js +2 -1
- package/dist/file-router/config/resolve.d.ts +43 -0
- package/dist/file-router/config/resolve.js +69 -0
- package/dist/file-router/{utils/validateOptions.d.ts → config/validate.d.ts} +11 -10
- package/dist/file-router/config/validate.js +280 -0
- package/dist/file-router/constants.d.ts +12 -2
- package/dist/file-router/constants.js +13 -3
- package/dist/file-router/generator/generateRoutes.d.ts +44 -13
- package/dist/file-router/generator/generateRoutes.js +159 -80
- package/dist/file-router/generator/generateTypes.d.ts +3 -29
- package/dist/file-router/generator/generateTypes.js +36 -41
- package/dist/file-router/global.d.ts +1 -1
- package/dist/file-router/index.d.ts +224 -90
- package/dist/file-router/index.js +571 -135
- package/dist/file-router/macros/astValueExtractor.d.ts +1 -1
- package/dist/file-router/macros/astValueExtractor.js +27 -7
- package/dist/file-router/macros/definePage.d.ts +20 -3
- package/dist/file-router/macros/definePage.js +120 -40
- package/dist/file-router/parser/exportChecker.d.ts +4 -23
- package/dist/file-router/parser/exportChecker.js +38 -79
- package/dist/file-router/parser/filterUtils.d.ts +25 -0
- package/dist/file-router/parser/filterUtils.js +43 -0
- package/dist/file-router/parser/index.d.ts +2 -1
- package/dist/file-router/parser/index.js +2 -1
- package/dist/file-router/parser/parsePage.d.ts +56 -9
- package/dist/file-router/parser/parsePage.js +194 -172
- package/dist/file-router/parser/routePath.d.ts +22 -0
- package/dist/file-router/parser/routePath.js +74 -0
- package/dist/file-router/types/hooks.d.ts +52 -0
- package/dist/file-router/types/index.d.ts +3 -0
- package/dist/file-router/types/index.js +1 -0
- package/dist/file-router/types/options.d.ts +279 -0
- package/dist/file-router/types/options.js +1 -0
- package/dist/file-router/types/route.d.ts +114 -0
- package/dist/file-router/types/route.js +1 -0
- package/dist/file-router/utils/fileReader.d.ts +11 -0
- package/dist/file-router/utils/fileReader.js +22 -0
- package/dist/file-router/utils/findRoute.d.ts +8 -0
- package/dist/file-router/utils/findRoute.js +22 -0
- package/dist/file-router/utils/index.d.ts +4 -2
- package/dist/file-router/utils/index.js +4 -2
- package/dist/file-router/utils/logger.d.ts +6 -6
- package/dist/file-router/utils/logger.js +44 -4
- package/dist/file-router/utils/pathStrategy.d.ts +28 -0
- package/dist/file-router/utils/{namingStrategy.js → pathStrategy.js} +18 -28
- package/dist/file-router/utils/pathUtils.d.ts +31 -0
- package/dist/file-router/utils/pathUtils.js +53 -1
- package/dist/plugin-vite/constant.d.ts +9 -0
- package/dist/plugin-vite/constant.js +9 -0
- package/dist/plugin-vite/index.d.ts +4 -24
- package/dist/plugin-vite/index.js +4 -94
- package/dist/plugin-vite/plugin.d.ts +86 -0
- package/dist/plugin-vite/plugin.js +181 -0
- package/dist/plugin-vite/watcher.d.ts +15 -0
- package/dist/plugin-vite/watcher.js +65 -0
- package/package.json +9 -7
- package/dist/file-router/config/configUtils.d.ts +0 -54
- package/dist/file-router/config/configUtils.js +0 -88
- package/dist/file-router/scanner/filterUtils.d.ts +0 -35
- package/dist/file-router/scanner/filterUtils.js +0 -188
- package/dist/file-router/scanner/index.d.ts +0 -8
- package/dist/file-router/scanner/index.js +0 -8
- package/dist/file-router/scanner/routeTreeBuilder.d.ts +0 -21
- package/dist/file-router/scanner/routeTreeBuilder.js +0 -312
- package/dist/file-router/scanner/scanPages.d.ts +0 -48
- package/dist/file-router/scanner/scanPages.js +0 -174
- package/dist/file-router/types.d.ts +0 -344
- package/dist/file-router/utils/namingStrategy.d.ts +0 -57
- package/dist/file-router/utils/validateOptions.js +0 -233
- /package/dist/{plugin-vite/auto-routes → auto-routes}/handleHotUpdate.js +0 -0
- /package/dist/{plugin-vite/auto-routes → auto-routes}/index.d.ts +0 -0
- /package/dist/{plugin-vite/auto-routes → auto-routes}/index.js +0 -0
- /package/dist/file-router/{types.js → types/hooks.js} +0 -0
package/dist/core/router/web.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isString, logger } from 'vitarx';
|
|
2
|
+
import { NavState } from '../common/constant.js';
|
|
2
3
|
import { parseHashContent } from '../common/utils.js';
|
|
3
4
|
import { normalizePath, parseQuery } from '../shared/utils.js';
|
|
4
5
|
import { Router } from './router.js';
|
|
@@ -11,6 +12,12 @@ export class WebRouter extends Router {
|
|
|
11
12
|
writable: true,
|
|
12
13
|
value: window.history
|
|
13
14
|
});
|
|
15
|
+
Object.defineProperty(this, "initialized", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true,
|
|
19
|
+
value: false
|
|
20
|
+
});
|
|
14
21
|
/**
|
|
15
22
|
* 处理浏览器历史记录的返回/前进事件
|
|
16
23
|
*/
|
|
@@ -48,10 +55,6 @@ export class WebRouter extends Router {
|
|
|
48
55
|
this.replace(this.urlToNavigateTarget()).then();
|
|
49
56
|
}
|
|
50
57
|
});
|
|
51
|
-
// 初始化路由
|
|
52
|
-
this.replace(this.urlToNavigateTarget()).then();
|
|
53
|
-
// 初始化时监听 popstate 事件,处理历史记录返回时的路由恢复
|
|
54
|
-
window.addEventListener('popstate', this.onPopState);
|
|
55
58
|
if (this.config.mode === 'hash') {
|
|
56
59
|
const { pathname, search, hash } = window.location;
|
|
57
60
|
if (!hash) {
|
|
@@ -59,7 +62,35 @@ export class WebRouter extends Router {
|
|
|
59
62
|
window.location.replace(path);
|
|
60
63
|
}
|
|
61
64
|
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 初始化路由器实例。
|
|
68
|
+
*
|
|
69
|
+
* 如果实例已经初始化,则直接返回当前实例以防止重复初始化。
|
|
70
|
+
* 初始化过程中会执行以下操作:
|
|
71
|
+
* 1. 根据目标 URL 执行初始路由替换;
|
|
72
|
+
* 2. 监听 `popstate` 事件,以处理浏览器历史记录返回时的路由恢复;
|
|
73
|
+
* 3. 监听 `hashchange` 事件,以处理浏览器 hash 值变化时的路由恢复。
|
|
74
|
+
*
|
|
75
|
+
* @returns {this} 返回当前路由器实例,支持链式调用。
|
|
76
|
+
*/
|
|
77
|
+
init() {
|
|
78
|
+
if (this.initialized)
|
|
79
|
+
return this;
|
|
80
|
+
this.initialized = true;
|
|
81
|
+
// 初始化路由
|
|
82
|
+
this.replace(this.urlToNavigateTarget()).then(res => {
|
|
83
|
+
if (__VITARX_DEV__) {
|
|
84
|
+
if (res.state !== NavState.success && res.state !== NavState.cancelled) {
|
|
85
|
+
logger.error(`[WebRouter] Initialization failed: ${res.message}`, res);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// 初始化时监听 popstate 事件,处理历史记录返回时的路由恢复
|
|
90
|
+
window.addEventListener('popstate', this.onPopState);
|
|
91
|
+
// 监听 hashchange 事件,处理 hash 值变化时的路由恢复
|
|
62
92
|
window.addEventListener('hashchange', this.onHashChange);
|
|
93
|
+
return this;
|
|
63
94
|
}
|
|
64
95
|
/**
|
|
65
96
|
* @inheritDoc
|
|
@@ -48,6 +48,13 @@ export interface UseLinkReturn {
|
|
|
48
48
|
*/
|
|
49
49
|
navigate: (e?: MouseEvent) => Promise<NavigateResult | void>;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* 判断是否为外部链接
|
|
53
|
+
*
|
|
54
|
+
* @param href - 链接地址
|
|
55
|
+
* @returns 是否为外部链接
|
|
56
|
+
*/
|
|
57
|
+
export declare function isExternalLink(href: string): boolean;
|
|
51
58
|
/**
|
|
52
59
|
* 创建一个链接助手,用于处理路由导航、生成链接属性及判断激活状态。
|
|
53
60
|
*
|
package/dist/core/shared/link.js
CHANGED
|
@@ -14,6 +14,15 @@ const handleTransition = async (callback) => {
|
|
|
14
14
|
const transition = document.startViewTransition(callback);
|
|
15
15
|
await transition.finished;
|
|
16
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* 判断是否为外部链接
|
|
19
|
+
*
|
|
20
|
+
* @param href - 链接地址
|
|
21
|
+
* @returns 是否为外部链接
|
|
22
|
+
*/
|
|
23
|
+
export function isExternalLink(href) {
|
|
24
|
+
return href.startsWith('http://') || href.startsWith('https://') || href.startsWith('//');
|
|
25
|
+
}
|
|
17
26
|
/**
|
|
18
27
|
* 创建一个链接助手,用于处理路由导航、生成链接属性及判断激活状态。
|
|
19
28
|
*
|
|
@@ -31,7 +40,6 @@ const handleTransition = async (callback) => {
|
|
|
31
40
|
*/
|
|
32
41
|
export function useLink(props) {
|
|
33
42
|
const router = useRouter();
|
|
34
|
-
const httpRegex = /^(https?):\/\/[^\s\/$.?#].\S*$/i;
|
|
35
43
|
/**
|
|
36
44
|
* 计算属性:解析目标路由
|
|
37
45
|
* @returns 返回解析后的路由位置对象,如果无效则返回 null
|
|
@@ -45,7 +53,7 @@ export function useLink(props) {
|
|
|
45
53
|
}
|
|
46
54
|
else if (isString(to)) {
|
|
47
55
|
// 如果是 HTTP/HTTPS 链接则返回 null
|
|
48
|
-
if (
|
|
56
|
+
if (isExternalLink(to))
|
|
49
57
|
return null;
|
|
50
58
|
target = { index: to };
|
|
51
59
|
}
|
|
@@ -100,12 +108,7 @@ export function useLink(props) {
|
|
|
100
108
|
return props.to.index;
|
|
101
109
|
}
|
|
102
110
|
if (isString(props.to)) {
|
|
103
|
-
|
|
104
|
-
return props.to;
|
|
105
|
-
}
|
|
106
|
-
if (props.to.startsWith('/')) {
|
|
107
|
-
return props.to;
|
|
108
|
-
}
|
|
111
|
+
return props.to;
|
|
109
112
|
}
|
|
110
113
|
return 'javascript:void(0)';
|
|
111
114
|
});
|
|
@@ -23,7 +23,6 @@ export declare function createRouteManager(routes: Route[], options?: RouteManag
|
|
|
23
23
|
* 创建Web模式路由实例
|
|
24
24
|
*
|
|
25
25
|
* @param options - 路由配置选项
|
|
26
|
-
* @param {RouterOptions} options - 路由配置选项
|
|
27
26
|
* @param options.routes - 路由配置表或管理器
|
|
28
27
|
* @param [options.base] - 基础路径
|
|
29
28
|
* @param [options.mode] - URL模式
|
|
@@ -33,9 +32,10 @@ export declare function createRouteManager(routes: Route[], options?: RouteManag
|
|
|
33
32
|
* @param [options.afterEach] - 全局后置钩子
|
|
34
33
|
* @param [options.missing] - 未匹配时要渲染的组件
|
|
35
34
|
* @param [options.onNotFound] - 导航不匹配时触发的回调函数
|
|
35
|
+
* @param [autoInit=true] - 是否自动初始化路由器
|
|
36
36
|
* @returns {WebRouter} 返回Web模式路由实例
|
|
37
37
|
*/
|
|
38
|
-
export declare function createWebRouter(options: RouterOptions): WebRouter;
|
|
38
|
+
export declare function createWebRouter(options: RouterOptions, autoInit?: boolean): WebRouter;
|
|
39
39
|
/**
|
|
40
40
|
* 创建内存模式路由实例
|
|
41
41
|
*
|
|
@@ -66,7 +66,7 @@ export declare function createMemoryRouter(options: RouterOptions): MemoryRouter
|
|
|
66
66
|
* @param [options.afterEach] - 全局后置钩子
|
|
67
67
|
* @param [options.missing] - 未匹配时要渲染的组件
|
|
68
68
|
* @param [options.onNotFound] - 导航不匹配时触发的回调函数
|
|
69
|
-
* @param
|
|
69
|
+
* @param [skipEnvWarn=false] - 是否跳过浏览器检查
|
|
70
70
|
* @returns {Router} 返回路由实例,根据环境返回不同类型的路由
|
|
71
71
|
*
|
|
72
72
|
*/
|
|
@@ -27,7 +27,6 @@ export function createRouteManager(routes, options) {
|
|
|
27
27
|
* 创建Web模式路由实例
|
|
28
28
|
*
|
|
29
29
|
* @param options - 路由配置选项
|
|
30
|
-
* @param {RouterOptions} options - 路由配置选项
|
|
31
30
|
* @param options.routes - 路由配置表或管理器
|
|
32
31
|
* @param [options.base] - 基础路径
|
|
33
32
|
* @param [options.mode] - URL模式
|
|
@@ -37,10 +36,14 @@ export function createRouteManager(routes, options) {
|
|
|
37
36
|
* @param [options.afterEach] - 全局后置钩子
|
|
38
37
|
* @param [options.missing] - 未匹配时要渲染的组件
|
|
39
38
|
* @param [options.onNotFound] - 导航不匹配时触发的回调函数
|
|
39
|
+
* @param [autoInit=true] - 是否自动初始化路由器
|
|
40
40
|
* @returns {WebRouter} 返回Web模式路由实例
|
|
41
41
|
*/
|
|
42
|
-
export function createWebRouter(options) {
|
|
43
|
-
|
|
42
|
+
export function createWebRouter(options, autoInit = true) {
|
|
43
|
+
const instance = new WebRouter(options);
|
|
44
|
+
if (autoInit)
|
|
45
|
+
instance.init();
|
|
46
|
+
return instance;
|
|
44
47
|
}
|
|
45
48
|
/**
|
|
46
49
|
* 创建内存模式路由实例
|
|
@@ -74,7 +77,7 @@ export function createMemoryRouter(options) {
|
|
|
74
77
|
* @param [options.afterEach] - 全局后置钩子
|
|
75
78
|
* @param [options.missing] - 未匹配时要渲染的组件
|
|
76
79
|
* @param [options.onNotFound] - 导航不匹配时触发的回调函数
|
|
77
|
-
* @param
|
|
80
|
+
* @param [skipEnvWarn=false] - 是否跳过浏览器检查
|
|
78
81
|
* @returns {Router} 返回路由实例,根据环境返回不同类型的路由
|
|
79
82
|
*
|
|
80
83
|
*/
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { CodeTransformHook, ExtendRouteHook, FileRouterOptions, GroupParser, ImportMode, PageDirOptions, PageParser, PageSource, PathStrategy, RouteNode } from '../types/index.js';
|
|
2
|
+
export type PageDirConfig = Required<PageDirOptions>;
|
|
3
|
+
/**
|
|
4
|
+
* 规范化后的配置
|
|
5
|
+
*/
|
|
6
|
+
export interface ResolvedConfig {
|
|
7
|
+
root: string;
|
|
8
|
+
pages: readonly PageDirConfig[];
|
|
9
|
+
pathStrategy: PathStrategy;
|
|
10
|
+
importMode: ImportMode;
|
|
11
|
+
injectImports: readonly string[];
|
|
12
|
+
dts: false | string;
|
|
13
|
+
layoutFileName: string;
|
|
14
|
+
configFileName: string;
|
|
15
|
+
transform?: CodeTransformHook;
|
|
16
|
+
extendRoute?: ExtendRouteHook;
|
|
17
|
+
beforeWriteRoutes?: (routes: RouteNode[]) => void | RouteNode[];
|
|
18
|
+
pageParser?: PageParser;
|
|
19
|
+
groupParser?: GroupParser;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 将 pages 配置规范化为 PageConfig 数组
|
|
23
|
+
*
|
|
24
|
+
* 支持四种输入格式:
|
|
25
|
+
* 1. 字符串:单个目录路径
|
|
26
|
+
* 2. 对象:单个目录配置
|
|
27
|
+
* 3. 字符串数组:多个目录路径
|
|
28
|
+
* 4. 对象数组:每个目录独立配置
|
|
29
|
+
*
|
|
30
|
+
* @param pages - 用户配置的 pages
|
|
31
|
+
* @param root - 项目根目录路径(用于解析相对路径)
|
|
32
|
+
* @returns - 规范化后的目录配置数组
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolvePageConfigs(pages: PageSource | readonly PageSource[], root: string): PageDirConfig[];
|
|
35
|
+
/**
|
|
36
|
+
* 规范化文件路由配置
|
|
37
|
+
*
|
|
38
|
+
* 将用户提供的配置转换为内部统一格式。
|
|
39
|
+
*
|
|
40
|
+
* @param options - 用户提供的配置选项
|
|
41
|
+
* @returns - 规范化后的配置对象
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveConfig(options: FileRouterOptions): ResolvedConfig;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview 配置处理工具模块
|
|
3
|
+
*
|
|
4
|
+
* 提供页面目录配置的处理和文件检查功能。
|
|
5
|
+
* 与构建工具无关,可在任何 Node.js 环境中使用。
|
|
6
|
+
*/
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { DEFAULT_CONFIG_FILE, DEFAULT_DTS_FILE, DEFAULT_EXCLUDE, DEFAULT_INCLUDE, DEFAULT_LAYOUT_FILE, DEFAULT_PAGES_DIR } from '../constants.js';
|
|
9
|
+
const DEFAULT_PAGE_CONFIG = {
|
|
10
|
+
exclude: DEFAULT_EXCLUDE,
|
|
11
|
+
include: DEFAULT_INCLUDE,
|
|
12
|
+
prefix: '/',
|
|
13
|
+
group: false
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* 将 pages 配置规范化为 PageConfig 数组
|
|
17
|
+
*
|
|
18
|
+
* 支持四种输入格式:
|
|
19
|
+
* 1. 字符串:单个目录路径
|
|
20
|
+
* 2. 对象:单个目录配置
|
|
21
|
+
* 3. 字符串数组:多个目录路径
|
|
22
|
+
* 4. 对象数组:每个目录独立配置
|
|
23
|
+
*
|
|
24
|
+
* @param pages - 用户配置的 pages
|
|
25
|
+
* @param root - 项目根目录路径(用于解析相对路径)
|
|
26
|
+
* @returns - 规范化后的目录配置数组
|
|
27
|
+
*/
|
|
28
|
+
export function resolvePageConfigs(pages, root) {
|
|
29
|
+
const list = Array.isArray(pages) ? pages : [pages];
|
|
30
|
+
return list.map(page => {
|
|
31
|
+
const config = typeof page === 'string' ? { dir: page } : page;
|
|
32
|
+
const resolved = {
|
|
33
|
+
...DEFAULT_PAGE_CONFIG,
|
|
34
|
+
...config,
|
|
35
|
+
dir: path.isAbsolute(config.dir) ? config.dir : path.resolve(root, config.dir)
|
|
36
|
+
};
|
|
37
|
+
if (resolved.prefix !== '/' && !resolved.prefix.startsWith('/')) {
|
|
38
|
+
resolved.prefix = '/' + resolved.prefix;
|
|
39
|
+
}
|
|
40
|
+
return resolved;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 规范化文件路由配置
|
|
45
|
+
*
|
|
46
|
+
* 将用户提供的配置转换为内部统一格式。
|
|
47
|
+
*
|
|
48
|
+
* @param options - 用户提供的配置选项
|
|
49
|
+
* @returns - 规范化后的配置对象
|
|
50
|
+
*/
|
|
51
|
+
export function resolveConfig(options) {
|
|
52
|
+
const { dts = false, root = process.cwd(), pages = DEFAULT_PAGES_DIR, importMode = 'lazy', injectImports = [], pathStrategy = 'kebab', layoutFileName = DEFAULT_LAYOUT_FILE, configFileName = DEFAULT_CONFIG_FILE, transform, extendRoute, beforeWriteRoutes, pageParser, groupParser } = options;
|
|
53
|
+
const resolvedPages = resolvePageConfigs(pages, root);
|
|
54
|
+
return {
|
|
55
|
+
dts: typeof dts === 'string' ? dts : dts ? DEFAULT_DTS_FILE : false,
|
|
56
|
+
root,
|
|
57
|
+
pages: resolvedPages,
|
|
58
|
+
importMode,
|
|
59
|
+
injectImports,
|
|
60
|
+
pathStrategy,
|
|
61
|
+
layoutFileName,
|
|
62
|
+
configFileName,
|
|
63
|
+
transform,
|
|
64
|
+
extendRoute,
|
|
65
|
+
beforeWriteRoutes,
|
|
66
|
+
pageParser,
|
|
67
|
+
groupParser
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -4,21 +4,22 @@
|
|
|
4
4
|
* 提供文件路由配置选项的验证功能,确保用户提供的配置符合要求。
|
|
5
5
|
* 当配置无效时抛出明确的错误信息,帮助用户快速定位问题。
|
|
6
6
|
*/
|
|
7
|
-
import type { FileRouterOptions } from '../types.js';
|
|
7
|
+
import type { FileRouterOptions } from '../types/index.js';
|
|
8
8
|
/**
|
|
9
9
|
* 验证插件配置选项
|
|
10
10
|
*
|
|
11
11
|
* 验证顺序:
|
|
12
12
|
* 1. root 配置
|
|
13
|
-
* 2.
|
|
14
|
-
* 3.
|
|
15
|
-
* 4.
|
|
16
|
-
* 5.
|
|
17
|
-
* 6.
|
|
18
|
-
* 7.
|
|
19
|
-
* 8.
|
|
20
|
-
* 9.
|
|
21
|
-
* 10.
|
|
13
|
+
* 2. pages 配置
|
|
14
|
+
* 3. pathStrategy 配置
|
|
15
|
+
* 4. importMode 配置
|
|
16
|
+
* 5. injectImports 配置
|
|
17
|
+
* 6. dts 配置
|
|
18
|
+
* 7. layoutFileName 配置
|
|
19
|
+
* 8. configFileName 配置
|
|
20
|
+
* 9. transform 配置
|
|
21
|
+
* 10. extendRoute 配置
|
|
22
|
+
* 11. pathParser 配置
|
|
22
23
|
*
|
|
23
24
|
* @param opts - 用户提供的配置选项
|
|
24
25
|
* @throws {Error} 当配置无效时抛出错误
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview 配置验证工具模块
|
|
3
|
+
*
|
|
4
|
+
* 提供文件路由配置选项的验证功能,确保用户提供的配置符合要求。
|
|
5
|
+
* 当配置无效时抛出明确的错误信息,帮助用户快速定位问题。
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 验证 pages 配置
|
|
9
|
+
*
|
|
10
|
+
* @param opts - 配置选项
|
|
11
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
12
|
+
*/
|
|
13
|
+
function validatePagesDir(opts) {
|
|
14
|
+
if (opts.pages === undefined)
|
|
15
|
+
return;
|
|
16
|
+
if (typeof opts.pages === 'string') {
|
|
17
|
+
if (opts.pages.trim() === '') {
|
|
18
|
+
throw new Error('options.pages 不能为空字符串');
|
|
19
|
+
}
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(opts.pages)) {
|
|
23
|
+
if (opts.pages.length === 0) {
|
|
24
|
+
throw new Error('options.pages 数组不能为空');
|
|
25
|
+
}
|
|
26
|
+
opts.pages.forEach((item, i) => {
|
|
27
|
+
validatePagesDirItem(item, i);
|
|
28
|
+
});
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
throw new Error('options.pages 必须是字符串、字符串数组或对象数组');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 验证 pages 数组中的单个项目
|
|
35
|
+
*
|
|
36
|
+
* @param item - 数组项
|
|
37
|
+
* @param index - 数组索引
|
|
38
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
39
|
+
*/
|
|
40
|
+
function validatePagesDirItem(item, index) {
|
|
41
|
+
if (typeof item === 'string') {
|
|
42
|
+
if (item.trim() === '') {
|
|
43
|
+
throw new Error(`options.pages[${index}] 不能为空字符串`);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (typeof item === 'object' && item !== null) {
|
|
48
|
+
const config = item;
|
|
49
|
+
if (!config.dir || typeof config.dir !== 'string' || config.dir.trim() === '') {
|
|
50
|
+
throw new Error(`options.pages[${index}].dir 必须是非空字符串`);
|
|
51
|
+
}
|
|
52
|
+
if (config.include !== undefined && !Array.isArray(config.include)) {
|
|
53
|
+
throw new Error(`options.pages[${index}].include 必须是数组`);
|
|
54
|
+
}
|
|
55
|
+
if (config.exclude !== undefined && !Array.isArray(config.exclude)) {
|
|
56
|
+
throw new Error(`options.pages[${index}].exclude 必须是数组`);
|
|
57
|
+
}
|
|
58
|
+
if (config.group === true &&
|
|
59
|
+
config.prefix !== undefined &&
|
|
60
|
+
typeof config.prefix === 'string' &&
|
|
61
|
+
config.prefix !== '/' &&
|
|
62
|
+
config.prefix.endsWith('/')) {
|
|
63
|
+
throw new Error(`options.pages[${index}].prefix 当 group 为 true 时不能以 '/' 结尾,请使用 '${config.prefix.slice(0, -1)}'`);
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
throw new Error(`options.pages[${index}] 必须是字符串或对象`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 验证 root 配置
|
|
71
|
+
*
|
|
72
|
+
* @param opts - 配置选项
|
|
73
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
74
|
+
*/
|
|
75
|
+
function validateRoot(opts) {
|
|
76
|
+
if (opts.root === undefined)
|
|
77
|
+
return;
|
|
78
|
+
if (typeof opts.root !== 'string') {
|
|
79
|
+
throw new Error('options.root 必须是字符串');
|
|
80
|
+
}
|
|
81
|
+
if (opts.root.trim() === '') {
|
|
82
|
+
throw new Error('options.root 不能为空字符串');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 验证 importMode 配置
|
|
87
|
+
*
|
|
88
|
+
* @param opts - 配置选项
|
|
89
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
90
|
+
*/
|
|
91
|
+
function validateImportMode(opts) {
|
|
92
|
+
if (opts.importMode === undefined)
|
|
93
|
+
return;
|
|
94
|
+
if (typeof opts.importMode === 'function')
|
|
95
|
+
return;
|
|
96
|
+
const validModes = ['lazy', 'sync'];
|
|
97
|
+
if (!validModes.includes(opts.importMode)) {
|
|
98
|
+
throw new Error(`options.importMode 必须是 'lazy'、'sync' 或函数`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* 验证 injectImports 配置
|
|
103
|
+
*
|
|
104
|
+
* @param opts - 配置选项
|
|
105
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
106
|
+
*/
|
|
107
|
+
function validateInjectImports(opts) {
|
|
108
|
+
if (opts.injectImports === undefined)
|
|
109
|
+
return;
|
|
110
|
+
if (!Array.isArray(opts.injectImports)) {
|
|
111
|
+
throw new Error('options.injectImports 必须是数组');
|
|
112
|
+
}
|
|
113
|
+
opts.injectImports.forEach((imp, i) => {
|
|
114
|
+
if (typeof imp !== 'string') {
|
|
115
|
+
throw new Error(`options.injectImports[${i}] 必须是字符串`);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 验证 namingStrategy 配置
|
|
121
|
+
*
|
|
122
|
+
* @param opts - 配置选项
|
|
123
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
124
|
+
*/
|
|
125
|
+
function validatePathStrategy(opts) {
|
|
126
|
+
if (opts.pathStrategy === undefined)
|
|
127
|
+
return;
|
|
128
|
+
const validStrategies = ['kebab', 'lowercase', 'raw'];
|
|
129
|
+
if (!validStrategies.includes(opts.pathStrategy)) {
|
|
130
|
+
throw new Error(`options.pathStrategy 必须是 'kebab'、'lowercase' 或 'raw'`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 验证 dts 配置
|
|
135
|
+
*
|
|
136
|
+
* @param opts - 配置选项
|
|
137
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
138
|
+
*/
|
|
139
|
+
function validateDts(opts) {
|
|
140
|
+
if (opts.dts === undefined)
|
|
141
|
+
return;
|
|
142
|
+
if (typeof opts.dts === 'boolean')
|
|
143
|
+
return;
|
|
144
|
+
if (typeof opts.dts === 'string') {
|
|
145
|
+
if (opts.dts.trim() === '') {
|
|
146
|
+
throw new Error('options.dts 为字符串时不能为空字符串');
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
throw new Error('options.dts 必须是 boolean 或 string');
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* 验证 layoutFileName 配置
|
|
154
|
+
*
|
|
155
|
+
* @param opts - 配置选项
|
|
156
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
157
|
+
*/
|
|
158
|
+
function validateLayoutFileName(opts) {
|
|
159
|
+
if (opts.layoutFileName === undefined)
|
|
160
|
+
return;
|
|
161
|
+
if (typeof opts.layoutFileName !== 'string') {
|
|
162
|
+
throw new Error('options.layoutFileName 必须是字符串');
|
|
163
|
+
}
|
|
164
|
+
if (opts.layoutFileName.trim() === '') {
|
|
165
|
+
throw new Error('options.layoutFileName 不能为空字符串');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* 验证 configFileName 配置
|
|
170
|
+
*
|
|
171
|
+
* @param opts - 配置选项
|
|
172
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
173
|
+
*/
|
|
174
|
+
function validateConfigFileName(opts) {
|
|
175
|
+
if (opts.configFileName === undefined)
|
|
176
|
+
return;
|
|
177
|
+
if (typeof opts.configFileName !== 'string') {
|
|
178
|
+
throw new Error('options.configFileName 必须是字符串');
|
|
179
|
+
}
|
|
180
|
+
if (opts.configFileName.trim() === '') {
|
|
181
|
+
throw new Error('options.configFileName 不能为空字符串');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* 验证 transform 配置
|
|
186
|
+
*
|
|
187
|
+
* @param opts - 配置选项
|
|
188
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
189
|
+
*/
|
|
190
|
+
function validateTransform(opts) {
|
|
191
|
+
if (opts.transform === undefined)
|
|
192
|
+
return;
|
|
193
|
+
if (typeof opts.transform !== 'function') {
|
|
194
|
+
throw new Error('options.transform 必须是函数');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* 验证 extendRoute 配置
|
|
199
|
+
*
|
|
200
|
+
* @param opts - 配置选项
|
|
201
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
202
|
+
*/
|
|
203
|
+
function validateExtendRoute(opts) {
|
|
204
|
+
if (opts.extendRoute === undefined)
|
|
205
|
+
return;
|
|
206
|
+
if (typeof opts.extendRoute !== 'function') {
|
|
207
|
+
throw new Error('options.extendRoute 必须是函数');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* 验证 beforeWriteRoutes 配置
|
|
212
|
+
* @param opts
|
|
213
|
+
*/
|
|
214
|
+
function validateBeforeWriteRoutes(opts) {
|
|
215
|
+
if (opts.beforeWriteRoutes === undefined)
|
|
216
|
+
return;
|
|
217
|
+
if (typeof opts.beforeWriteRoutes !== 'function') {
|
|
218
|
+
throw new Error('options.beforeWriteRoutes 必须是函数');
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 验证 pathParser 配置
|
|
223
|
+
*
|
|
224
|
+
* @param opts - 配置选项
|
|
225
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
226
|
+
*/
|
|
227
|
+
function validatePathParser(opts) {
|
|
228
|
+
if (opts.pageParser === undefined)
|
|
229
|
+
return;
|
|
230
|
+
if (typeof opts.pageParser !== 'function') {
|
|
231
|
+
throw new Error('options.pathParser 必须是函数');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* 验证 groupParser 配置
|
|
236
|
+
*
|
|
237
|
+
* @param opts - 配置选项
|
|
238
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
239
|
+
*/
|
|
240
|
+
function validateGroupParser(opts) {
|
|
241
|
+
if (opts.groupParser === undefined)
|
|
242
|
+
return;
|
|
243
|
+
if (typeof opts.groupParser !== 'function') {
|
|
244
|
+
throw new Error('options.groupParser 必须是函数');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* 验证插件配置选项
|
|
249
|
+
*
|
|
250
|
+
* 验证顺序:
|
|
251
|
+
* 1. root 配置
|
|
252
|
+
* 2. pages 配置
|
|
253
|
+
* 3. pathStrategy 配置
|
|
254
|
+
* 4. importMode 配置
|
|
255
|
+
* 5. injectImports 配置
|
|
256
|
+
* 6. dts 配置
|
|
257
|
+
* 7. layoutFileName 配置
|
|
258
|
+
* 8. configFileName 配置
|
|
259
|
+
* 9. transform 配置
|
|
260
|
+
* 10. extendRoute 配置
|
|
261
|
+
* 11. pathParser 配置
|
|
262
|
+
*
|
|
263
|
+
* @param opts - 用户提供的配置选项
|
|
264
|
+
* @throws {Error} 当配置无效时抛出错误
|
|
265
|
+
*/
|
|
266
|
+
export function validateOptions(opts) {
|
|
267
|
+
validateRoot(opts);
|
|
268
|
+
validatePagesDir(opts);
|
|
269
|
+
validatePathStrategy(opts);
|
|
270
|
+
validateImportMode(opts);
|
|
271
|
+
validateInjectImports(opts);
|
|
272
|
+
validateDts(opts);
|
|
273
|
+
validateLayoutFileName(opts);
|
|
274
|
+
validateConfigFileName(opts);
|
|
275
|
+
validateTransform(opts);
|
|
276
|
+
validateExtendRoute(opts);
|
|
277
|
+
validateBeforeWriteRoutes(opts);
|
|
278
|
+
validatePathParser(opts);
|
|
279
|
+
validateGroupParser(opts);
|
|
280
|
+
}
|
|
@@ -3,9 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 定义文件路由的默认配置常量。
|
|
5
5
|
*/
|
|
6
|
-
/** 支持的页面文件扩展名列表 */
|
|
7
|
-
export declare const DEFAULT_EXTENSIONS: string[];
|
|
8
6
|
/** 默认的页面目录路径 */
|
|
9
7
|
export declare const DEFAULT_PAGES_DIR = "src/pages";
|
|
8
|
+
/** 默认的类型定义文件路径 */
|
|
9
|
+
export declare const DEFAULT_DTS_FILE = "router.d.ts";
|
|
10
10
|
/** 默认的包含模式 */
|
|
11
11
|
export declare const DEFAULT_INCLUDE: string[];
|
|
12
|
+
/** 默认的排除模式 */
|
|
13
|
+
export declare const DEFAULT_EXCLUDE: string[];
|
|
14
|
+
/**
|
|
15
|
+
* 布局文件名前缀
|
|
16
|
+
*/
|
|
17
|
+
export declare const DEFAULT_LAYOUT_FILE = "_layout";
|
|
18
|
+
/**
|
|
19
|
+
* 配置文件名
|
|
20
|
+
*/
|
|
21
|
+
export declare const DEFAULT_CONFIG_FILE = "_config";
|