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.
Files changed (93) hide show
  1. package/README.md +42 -17
  2. package/dist/{plugin-vite/auto-routes → auto-routes}/handleHotUpdate.d.ts +1 -1
  3. package/dist/components/RouterView.js +5 -4
  4. package/dist/core/common/constant.d.ts +5 -6
  5. package/dist/core/common/constant.js +5 -6
  6. package/dist/core/common/utils.js +2 -1
  7. package/dist/core/router/checkOptions.d.ts +11 -0
  8. package/dist/core/router/checkOptions.js +119 -0
  9. package/dist/core/router/manager.js +27 -23
  10. package/dist/core/router/router.d.ts +154 -1
  11. package/dist/core/router/router.js +303 -230
  12. package/dist/core/router/web.d.ts +13 -0
  13. package/dist/core/router/web.js +35 -4
  14. package/dist/core/shared/link.d.ts +7 -0
  15. package/dist/core/shared/link.js +11 -8
  16. package/dist/core/shared/route.js +1 -2
  17. package/dist/core/shared/router.d.ts +3 -3
  18. package/dist/core/shared/router.js +7 -4
  19. package/dist/core/types/options.d.ts +2 -0
  20. package/dist/file-router/config/index.d.ts +2 -1
  21. package/dist/file-router/config/index.js +2 -1
  22. package/dist/file-router/config/resolve.d.ts +43 -0
  23. package/dist/file-router/config/resolve.js +69 -0
  24. package/dist/file-router/{utils/validateOptions.d.ts → config/validate.d.ts} +11 -10
  25. package/dist/file-router/config/validate.js +280 -0
  26. package/dist/file-router/constants.d.ts +12 -2
  27. package/dist/file-router/constants.js +13 -3
  28. package/dist/file-router/generator/generateRoutes.d.ts +44 -13
  29. package/dist/file-router/generator/generateRoutes.js +159 -80
  30. package/dist/file-router/generator/generateTypes.d.ts +3 -29
  31. package/dist/file-router/generator/generateTypes.js +36 -41
  32. package/dist/file-router/global.d.ts +1 -1
  33. package/dist/file-router/index.d.ts +224 -90
  34. package/dist/file-router/index.js +571 -135
  35. package/dist/file-router/macros/astValueExtractor.d.ts +1 -1
  36. package/dist/file-router/macros/astValueExtractor.js +27 -7
  37. package/dist/file-router/macros/definePage.d.ts +20 -3
  38. package/dist/file-router/macros/definePage.js +120 -40
  39. package/dist/file-router/parser/exportChecker.d.ts +4 -23
  40. package/dist/file-router/parser/exportChecker.js +38 -79
  41. package/dist/file-router/parser/filterUtils.d.ts +25 -0
  42. package/dist/file-router/parser/filterUtils.js +43 -0
  43. package/dist/file-router/parser/index.d.ts +2 -1
  44. package/dist/file-router/parser/index.js +2 -1
  45. package/dist/file-router/parser/parsePage.d.ts +56 -9
  46. package/dist/file-router/parser/parsePage.js +194 -172
  47. package/dist/file-router/parser/routePath.d.ts +22 -0
  48. package/dist/file-router/parser/routePath.js +74 -0
  49. package/dist/file-router/types/hooks.d.ts +52 -0
  50. package/dist/file-router/types/index.d.ts +3 -0
  51. package/dist/file-router/types/index.js +1 -0
  52. package/dist/file-router/types/options.d.ts +279 -0
  53. package/dist/file-router/types/options.js +1 -0
  54. package/dist/file-router/types/route.d.ts +114 -0
  55. package/dist/file-router/types/route.js +1 -0
  56. package/dist/file-router/utils/fileReader.d.ts +11 -0
  57. package/dist/file-router/utils/fileReader.js +22 -0
  58. package/dist/file-router/utils/findRoute.d.ts +8 -0
  59. package/dist/file-router/utils/findRoute.js +22 -0
  60. package/dist/file-router/utils/index.d.ts +4 -2
  61. package/dist/file-router/utils/index.js +4 -2
  62. package/dist/file-router/utils/logger.d.ts +6 -6
  63. package/dist/file-router/utils/logger.js +44 -4
  64. package/dist/file-router/utils/pathStrategy.d.ts +28 -0
  65. package/dist/file-router/utils/{namingStrategy.js → pathStrategy.js} +18 -28
  66. package/dist/file-router/utils/pathUtils.d.ts +31 -0
  67. package/dist/file-router/utils/pathUtils.js +53 -1
  68. package/dist/plugin-vite/constant.d.ts +9 -0
  69. package/dist/plugin-vite/constant.js +9 -0
  70. package/dist/plugin-vite/index.d.ts +4 -24
  71. package/dist/plugin-vite/index.js +4 -94
  72. package/dist/plugin-vite/plugin.d.ts +86 -0
  73. package/dist/plugin-vite/plugin.js +181 -0
  74. package/dist/plugin-vite/watcher.d.ts +15 -0
  75. package/dist/plugin-vite/watcher.js +65 -0
  76. package/package.json +9 -7
  77. package/dist/file-router/config/configUtils.d.ts +0 -54
  78. package/dist/file-router/config/configUtils.js +0 -88
  79. package/dist/file-router/scanner/filterUtils.d.ts +0 -35
  80. package/dist/file-router/scanner/filterUtils.js +0 -188
  81. package/dist/file-router/scanner/index.d.ts +0 -8
  82. package/dist/file-router/scanner/index.js +0 -8
  83. package/dist/file-router/scanner/routeTreeBuilder.d.ts +0 -21
  84. package/dist/file-router/scanner/routeTreeBuilder.js +0 -312
  85. package/dist/file-router/scanner/scanPages.d.ts +0 -48
  86. package/dist/file-router/scanner/scanPages.js +0 -174
  87. package/dist/file-router/types.d.ts +0 -344
  88. package/dist/file-router/utils/namingStrategy.d.ts +0 -57
  89. package/dist/file-router/utils/validateOptions.js +0 -233
  90. /package/dist/{plugin-vite/auto-routes → auto-routes}/handleHotUpdate.js +0 -0
  91. /package/dist/{plugin-vite/auto-routes → auto-routes}/index.d.ts +0 -0
  92. /package/dist/{plugin-vite/auto-routes → auto-routes}/index.js +0 -0
  93. /package/dist/file-router/{types.js → types/hooks.js} +0 -0
@@ -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
  *
@@ -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 (httpRegex.test(to))
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
- if (httpRegex.test(props.to)) {
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
  });
@@ -20,8 +20,7 @@ export function useRoute(global = false) {
20
20
  return route;
21
21
  }
22
22
  const record = route.matched[depth];
23
- if (!record) {
23
+ if (!record)
24
24
  return route;
25
- }
26
25
  return createRouteProxy(route, record);
27
26
  }
@@ -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 {boolean} [skipEnvWarn=false] - 是否跳过浏览器检查
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
- return new WebRouter(options);
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 {boolean} [skipEnvWarn=false] - 是否跳过浏览器检查
80
+ * @param [skipEnvWarn=false] - 是否跳过浏览器检查
78
81
  * @returns {Router} 返回路由实例,根据环境返回不同类型的路由
79
82
  *
80
83
  */
@@ -48,6 +48,8 @@ export interface RouterOptions {
48
48
  * 全局 props 注入配置
49
49
  *
50
50
  * 优先级低于 route 的 props 配置
51
+ *
52
+ * @default true
51
53
  */
52
54
  props?: boolean | InjectPropsHandler;
53
55
  /**
@@ -3,4 +3,5 @@
3
3
  *
4
4
  * 导出所有配置相关功能,提供统一的访问入口。
5
5
  */
6
- export * from './configUtils.js';
6
+ export * from './resolve.js';
7
+ export * from './validate.js';
@@ -3,4 +3,5 @@
3
3
  *
4
4
  * 导出所有配置相关功能,提供统一的访问入口。
5
5
  */
6
- export * from './configUtils.js';
6
+ export * from './resolve.js';
7
+ export * from './validate.js';
@@ -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. prefix 配置
14
- * 3. pages 配置
15
- * 4. extensions 配置
16
- * 5. include 配置
17
- * 6. exclude 配置
18
- * 7. importMode 配置
19
- * 8. extendRoute 配置
20
- * 9. injectImports 配置
21
- * 10. namingStrategy 配置
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";