@4399ywkf/core 5.3.1 → 5.4.1
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/biome.json +34 -30
- package/dist/cli/index.js +152 -101
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.js +120 -75
- package/dist/config/index.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +163 -116
- package/dist/index.js.map +1 -1
- package/dist/plugin/index.d.ts +3 -6
- package/dist/plugin/index.js.map +1 -1
- package/dist/router/index.d.ts +20 -20
- package/dist/router/index.js +8 -10
- package/dist/router/index.js.map +1 -1
- package/dist/rspack/index.d.ts +2 -2
- package/dist/rspack/index.js +133 -86
- package/dist/rspack/index.js.map +1 -1
- package/dist/runtime/index.d.ts +17 -17
- package/dist/runtime/index.js +11 -15
- package/dist/runtime/index.js.map +1 -1
- package/dist/{schema-Ade9gA3U.d.ts → schema-BblOKuYl.d.ts} +223 -223
- package/dist/{types-ZJhd87ue.d.ts → types-DZ7Nz9bQ.d.ts} +54 -54
- package/package.json +7 -6
package/dist/plugin/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Q as YwkfPlugin, e as PluginHooks, Y as YwkfConfig, f as PluginConfig, U as RouteItem } from '../schema-
|
|
2
|
-
export { y as BuildHooks, C as CodeInjection, V as DefinePlugin, F as GeneratedFile, G as GeneratorContext, J as GeneratorHooks, W as PluginAPI, K as PluginContext, X as PluginLogger, L as RouterHooks, N as RuntimeHooks } from '../schema-
|
|
1
|
+
import { Q as YwkfPlugin, e as PluginHooks, Y as YwkfConfig, f as PluginConfig, U as RouteItem } from '../schema-BblOKuYl.js';
|
|
2
|
+
export { y as BuildHooks, C as CodeInjection, V as DefinePlugin, F as GeneratedFile, G as GeneratorContext, J as GeneratorHooks, W as PluginAPI, K as PluginContext, X as PluginLogger, L as RouterHooks, N as RuntimeHooks } from '../schema-BblOKuYl.js';
|
|
3
3
|
import { Configuration } from '@rspack/core';
|
|
4
|
-
import { a as AppConfig, P as ProviderConfig } from '../types-
|
|
4
|
+
import { a as AppConfig, P as ProviderConfig } from '../types-DZ7Nz9bQ.js';
|
|
5
5
|
import 'react';
|
|
6
6
|
import 'react-router';
|
|
7
7
|
|
|
@@ -39,9 +39,6 @@ declare function definePlugin(plugin: YwkfPlugin): YwkfPlugin;
|
|
|
39
39
|
* ```
|
|
40
40
|
*/
|
|
41
41
|
declare function createPlugin<T = Record<string, unknown>>(factory: (options?: T) => YwkfPlugin): (options?: T) => YwkfPlugin;
|
|
42
|
-
/**
|
|
43
|
-
* 组合多个插件钩子
|
|
44
|
-
*/
|
|
45
42
|
declare function composeHooks(...hooksList: PluginHooks[]): PluginHooks;
|
|
46
43
|
|
|
47
44
|
/**
|
package/dist/plugin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugin/define.ts","../../src/plugin/manager.ts"],"sourcesContent":["import type { PluginHooks, YwkfPlugin } from \"./types.js\";\n\n/**\n * 定义插件的辅助函数\n *\n * @example\n * ```ts\n * export default definePlugin({\n * name: \"my-plugin\",\n * setup(context) {\n * return {\n * modifyRspackConfig(config) {\n * // 修改配置\n * return config;\n * },\n * };\n * },\n * });\n * ```\n */\nexport function definePlugin(plugin: YwkfPlugin): YwkfPlugin {\n return plugin;\n}\n\n/**\n * 创建带配置的插件工厂\n *\n * @example\n * ```ts\n * export default createPlugin<{ apiUrl: string }>((options) => ({\n * name: \"api-plugin\",\n * setup(context) {\n * console.log(\"API URL:\", options?.apiUrl);\n * return {};\n * },\n * }));\n * ```\n */\nexport function createPlugin<T = Record<string, unknown>>(\n factory: (options?: T) => YwkfPlugin,\n): (options?: T) => YwkfPlugin {\n return factory;\n}\n\n/**\n * 组合多个插件钩子\n */\nexport function composeHooks(...hooksList: PluginHooks[]): PluginHooks {\n const composed: Record<string, Function> = {};\n\n for (const hooks of hooksList) {\n for (const [key, value] of Object.entries(hooks)) {\n if (value) {\n const existing = composed[key];\n if (existing) {\n composed[key] = async (...args: unknown[]) => {\n await existing(...args);\n return (value as Function)(...args);\n };\n } else {\n composed[key] = value as Function;\n }\n }\n }\n }\n\n return composed as PluginHooks;\n}\n","import type { Configuration as RspackConfig } from \"@rspack/core\";\nimport type { YwkfConfig } from \"../config/schema.js\";\nimport type { RouteItem } from \"../router/types.js\";\nimport type { AppConfig, ProviderConfig } from \"../runtime/types.js\";\nimport type {\n PluginConfig,\n PluginContext,\n PluginHooks,\n PluginLogger,\n YwkfPlugin,\n} from \"./types.js\";\n\n/**\n * 创建插件日志工具\n */\nfunction createLogger(pluginName: string): PluginLogger {\n const prefix = `[${pluginName}]`;\n const verbose = !!process.env.DEBUG;\n\n return {\n info: (msg) => {\n if (verbose) console.log(`${prefix} ${msg}`);\n },\n warn: (msg) => console.warn(`${prefix} ${msg}`),\n error: (msg) => console.error(`${prefix} ${msg}`),\n debug: (msg) => {\n if (verbose) console.debug(`${prefix} ${msg}`);\n },\n };\n}\n\n/**\n * 解析插件配置\n */\nasync function resolvePlugin(\n pluginConfig: PluginConfig,\n _cwd: string,\n): Promise<{ plugin: YwkfPlugin; options: Record<string, unknown> }> {\n let plugin: YwkfPlugin;\n let options: Record<string, unknown> = {};\n\n if (typeof pluginConfig === \"string\") {\n // 字符串:插件包名\n const module = await import(pluginConfig);\n plugin = module.default || module;\n } else if (Array.isArray(pluginConfig)) {\n // 数组:[插件, 配置]\n const [pluginOrName, pluginOptions] = pluginConfig;\n options = pluginOptions;\n\n if (typeof pluginOrName === \"string\") {\n const module = await import(pluginOrName);\n plugin = module.default || module;\n } else {\n plugin = pluginOrName;\n }\n } else {\n // 插件对象\n plugin = pluginConfig;\n }\n\n // 如果是工厂函数,调用它\n if (typeof plugin === \"function\") {\n plugin = (plugin as (opts?: Record<string, unknown>) => YwkfPlugin)(options);\n }\n\n return { plugin, options };\n}\n\n/**\n * 插件管理器\n */\nexport class PluginManager {\n private plugins: Map<string, { plugin: YwkfPlugin; hooks: PluginHooks }> = new Map();\n private context: PluginContext;\n\n constructor(config: Required<YwkfConfig>, cwd: string, isDev: boolean) {\n this.context = {\n cwd,\n isDev,\n isProd: !isDev,\n config,\n logger: createLogger(\"PluginManager\"),\n };\n }\n\n /**\n * 加载并初始化所有插件\n */\n async loadPlugins(pluginConfigs: PluginConfig[]): Promise<void> {\n for (const pluginConfig of pluginConfigs) {\n try {\n const { plugin } = await resolvePlugin(pluginConfig, this.context.cwd);\n\n if (this.plugins.has(plugin.name)) {\n this.context.logger.warn(`插件 ${plugin.name} 已加载,跳过重复加载`);\n continue;\n }\n\n // 创建插件专属 logger\n const pluginContext: PluginContext = {\n ...this.context,\n logger: createLogger(plugin.name),\n };\n\n // 调用插件 setup\n const hooks = await plugin.setup(pluginContext);\n\n this.plugins.set(plugin.name, { plugin, hooks });\n this.context.logger.info(`已加载插件: ${plugin.name}`);\n } catch (error) {\n this.context.logger.error(`加载插件失败: ${String(pluginConfig)} - ${error}`);\n }\n }\n }\n\n /**\n * 执行 modifyRspackConfig 钩子\n */\n async applyRspackConfigHooks(config: RspackConfig): Promise<RspackConfig> {\n let result = config;\n\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.modifyRspackConfig) {\n try {\n const modified = await hooks.modifyRspackConfig(result, this.context);\n if (modified) {\n result = modified;\n }\n } catch (error) {\n this.context.logger.error(`插件 ${name} modifyRspackConfig 执行失败: ${error}`);\n }\n }\n }\n\n return result;\n }\n\n /**\n * 执行 modifyRoutes 钩子\n */\n async applyRoutesHooks(routes: RouteItem[]): Promise<RouteItem[]> {\n let result = routes;\n\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.modifyRoutes) {\n try {\n const modified = await hooks.modifyRoutes(result, this.context);\n if (modified) {\n result = modified;\n }\n } catch (error) {\n this.context.logger.error(`插件 ${name} modifyRoutes 执行失败: ${error}`);\n }\n }\n }\n\n return result;\n }\n\n /**\n * 执行 modifyAppConfig 钩子\n */\n applyAppConfigHooks(appConfig: AppConfig): AppConfig {\n let result = appConfig;\n\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.modifyAppConfig) {\n try {\n const modified = hooks.modifyAppConfig(result, this.context);\n if (modified) {\n result = modified;\n }\n } catch (error) {\n this.context.logger.error(`插件 ${name} modifyAppConfig 执行失败: ${error}`);\n }\n }\n }\n\n return result;\n }\n\n /**\n * 收集所有插件的 Provider\n */\n collectProviders(): ProviderConfig[] {\n const providers: ProviderConfig[] = [];\n\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.addProvider) {\n try {\n const result = hooks.addProvider(this.context);\n if (Array.isArray(result)) {\n providers.push(...result);\n } else if (result) {\n providers.push(result);\n }\n } catch (error) {\n this.context.logger.error(`插件 ${name} addProvider 执行失败: ${error}`);\n }\n }\n }\n\n return providers;\n }\n\n /**\n * 执行 beforeBuild 钩子\n */\n async runBeforeBuild(): Promise<void> {\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.beforeBuild) {\n try {\n await hooks.beforeBuild(this.context);\n } catch (error) {\n this.context.logger.error(`插件 ${name} beforeBuild 执行失败: ${error}`);\n }\n }\n }\n }\n\n /**\n * 执行 afterBuild 钩子\n */\n async runAfterBuild(stats: { success: boolean; errors?: string[] }): Promise<void> {\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.afterBuild) {\n try {\n await hooks.afterBuild(this.context, stats);\n } catch (error) {\n this.context.logger.error(`插件 ${name} afterBuild 执行失败: ${error}`);\n }\n }\n }\n }\n\n /**\n * 执行 beforeDevServer 钩子\n */\n async runBeforeDevServer(): Promise<void> {\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.beforeDevServer) {\n try {\n await hooks.beforeDevServer(this.context);\n } catch (error) {\n this.context.logger.error(`插件 ${name} beforeDevServer 执行失败: ${error}`);\n }\n }\n }\n }\n\n /**\n * 执行 afterDevServer 钩子\n */\n async runAfterDevServer(server: { port: number; host: string }): Promise<void> {\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.afterDevServer) {\n try {\n await hooks.afterDevServer(this.context, server);\n } catch (error) {\n this.context.logger.error(`插件 ${name} afterDevServer 执行失败: ${error}`);\n }\n }\n }\n }\n\n /**\n * 获取所有已加载的插件名称\n */\n getPluginNames(): string[] {\n return Array.from(this.plugins.keys());\n }\n\n /**\n * 获取所有已加载的插件\n */\n getPlugins(): YwkfPlugin[] {\n return Array.from(this.plugins.values()).map((p) => p.plugin);\n }\n\n /**\n * 获取所有已加载的插件钩子\n */\n getPluginHooks(): PluginHooks[] {\n return Array.from(this.plugins.values()).map((p) => p.hooks);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugin/define.ts","../../src/plugin/manager.ts"],"sourcesContent":["import type { PluginHooks, YwkfPlugin } from './types.js';\n\n/**\n * 定义插件的辅助函数\n *\n * @example\n * ```ts\n * export default definePlugin({\n * name: \"my-plugin\",\n * setup(context) {\n * return {\n * modifyRspackConfig(config) {\n * // 修改配置\n * return config;\n * },\n * };\n * },\n * });\n * ```\n */\nexport function definePlugin(plugin: YwkfPlugin): YwkfPlugin {\n return plugin;\n}\n\n/**\n * 创建带配置的插件工厂\n *\n * @example\n * ```ts\n * export default createPlugin<{ apiUrl: string }>((options) => ({\n * name: \"api-plugin\",\n * setup(context) {\n * console.log(\"API URL:\", options?.apiUrl);\n * return {};\n * },\n * }));\n * ```\n */\nexport function createPlugin<T = Record<string, unknown>>(\n factory: (options?: T) => YwkfPlugin,\n): (options?: T) => YwkfPlugin {\n return factory;\n}\n\n/**\n * 组合多个插件钩子\n */\ntype HookFn = (...args: unknown[]) => unknown;\n\nexport function composeHooks(...hooksList: PluginHooks[]): PluginHooks {\n const composed: Record<string, HookFn> = {};\n\n for (const hooks of hooksList) {\n for (const [key, value] of Object.entries(hooks)) {\n if (value) {\n const existing = composed[key];\n if (existing) {\n composed[key] = async (...args: unknown[]) => {\n await existing(...args);\n return (value as HookFn)(...args);\n };\n } else {\n composed[key] = value as HookFn;\n }\n }\n }\n }\n\n return composed as PluginHooks;\n}\n","import type { Configuration as RspackConfig } from '@rspack/core';\n\nimport type { YwkfConfig } from '../config/schema.js';\nimport type { RouteItem } from '../router/types.js';\nimport type { AppConfig, ProviderConfig } from '../runtime/types.js';\nimport type {\n PluginConfig,\n PluginContext,\n PluginHooks,\n PluginLogger,\n YwkfPlugin,\n} from './types.js';\n\n/**\n * 创建插件日志工具\n */\nfunction createLogger(pluginName: string): PluginLogger {\n const prefix = `[${pluginName}]`;\n const verbose = !!process.env.DEBUG;\n\n return {\n info: (msg) => {\n if (verbose) console.log(`${prefix} ${msg}`);\n },\n warn: (msg) => console.warn(`${prefix} ${msg}`),\n error: (msg) => console.error(`${prefix} ${msg}`),\n debug: (msg) => {\n if (verbose) console.debug(`${prefix} ${msg}`);\n },\n };\n}\n\n/**\n * 解析插件配置\n */\nasync function resolvePlugin(\n pluginConfig: PluginConfig,\n _cwd: string,\n): Promise<{ plugin: YwkfPlugin; options: Record<string, unknown> }> {\n let plugin: YwkfPlugin;\n let options: Record<string, unknown> = {};\n\n if (typeof pluginConfig === 'string') {\n // 字符串:插件包名\n const module = await import(pluginConfig);\n plugin = module.default || module;\n } else if (Array.isArray(pluginConfig)) {\n // 数组:[插件, 配置]\n const [pluginOrName, pluginOptions] = pluginConfig;\n options = pluginOptions;\n\n if (typeof pluginOrName === 'string') {\n const module = await import(pluginOrName);\n plugin = module.default || module;\n } else {\n plugin = pluginOrName;\n }\n } else {\n // 插件对象\n plugin = pluginConfig;\n }\n\n // 如果是工厂函数,调用它\n if (typeof plugin === 'function') {\n plugin = (plugin as (opts?: Record<string, unknown>) => YwkfPlugin)(options);\n }\n\n return { plugin, options };\n}\n\n/**\n * 插件管理器\n */\nexport class PluginManager {\n private plugins: Map<string, { plugin: YwkfPlugin; hooks: PluginHooks }> = new Map();\n private context: PluginContext;\n\n constructor(config: Required<YwkfConfig>, cwd: string, isDev: boolean) {\n this.context = {\n cwd,\n isDev,\n isProd: !isDev,\n config,\n logger: createLogger('PluginManager'),\n };\n }\n\n /**\n * 加载并初始化所有插件\n */\n async loadPlugins(pluginConfigs: PluginConfig[]): Promise<void> {\n for (const pluginConfig of pluginConfigs) {\n try {\n const { plugin } = await resolvePlugin(pluginConfig, this.context.cwd);\n\n if (this.plugins.has(plugin.name)) {\n this.context.logger.warn(`插件 ${plugin.name} 已加载,跳过重复加载`);\n continue;\n }\n\n // 创建插件专属 logger\n const pluginContext: PluginContext = {\n ...this.context,\n logger: createLogger(plugin.name),\n };\n\n // 调用插件 setup\n const hooks = await plugin.setup(pluginContext);\n\n this.plugins.set(plugin.name, { plugin, hooks });\n this.context.logger.info(`已加载插件: ${plugin.name}`);\n } catch (error) {\n this.context.logger.error(`加载插件失败: ${String(pluginConfig)} - ${error}`);\n }\n }\n }\n\n /**\n * 执行 modifyRspackConfig 钩子\n */\n async applyRspackConfigHooks(config: RspackConfig): Promise<RspackConfig> {\n let result = config;\n\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.modifyRspackConfig) {\n try {\n const modified = await hooks.modifyRspackConfig(result, this.context);\n if (modified) {\n result = modified;\n }\n } catch (error) {\n this.context.logger.error(`插件 ${name} modifyRspackConfig 执行失败: ${error}`);\n }\n }\n }\n\n return result;\n }\n\n /**\n * 执行 modifyRoutes 钩子\n */\n async applyRoutesHooks(routes: RouteItem[]): Promise<RouteItem[]> {\n let result = routes;\n\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.modifyRoutes) {\n try {\n const modified = await hooks.modifyRoutes(result, this.context);\n if (modified) {\n result = modified;\n }\n } catch (error) {\n this.context.logger.error(`插件 ${name} modifyRoutes 执行失败: ${error}`);\n }\n }\n }\n\n return result;\n }\n\n /**\n * 执行 modifyAppConfig 钩子\n */\n applyAppConfigHooks(appConfig: AppConfig): AppConfig {\n let result = appConfig;\n\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.modifyAppConfig) {\n try {\n const modified = hooks.modifyAppConfig(result, this.context);\n if (modified) {\n result = modified;\n }\n } catch (error) {\n this.context.logger.error(`插件 ${name} modifyAppConfig 执行失败: ${error}`);\n }\n }\n }\n\n return result;\n }\n\n /**\n * 收集所有插件的 Provider\n */\n collectProviders(): ProviderConfig[] {\n const providers: ProviderConfig[] = [];\n\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.addProvider) {\n try {\n const result = hooks.addProvider(this.context);\n if (Array.isArray(result)) {\n providers.push(...result);\n } else if (result) {\n providers.push(result);\n }\n } catch (error) {\n this.context.logger.error(`插件 ${name} addProvider 执行失败: ${error}`);\n }\n }\n }\n\n return providers;\n }\n\n /**\n * 执行 beforeBuild 钩子\n */\n async runBeforeBuild(): Promise<void> {\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.beforeBuild) {\n try {\n await hooks.beforeBuild(this.context);\n } catch (error) {\n this.context.logger.error(`插件 ${name} beforeBuild 执行失败: ${error}`);\n }\n }\n }\n }\n\n /**\n * 执行 afterBuild 钩子\n */\n async runAfterBuild(stats: { success: boolean; errors?: string[] }): Promise<void> {\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.afterBuild) {\n try {\n await hooks.afterBuild(this.context, stats);\n } catch (error) {\n this.context.logger.error(`插件 ${name} afterBuild 执行失败: ${error}`);\n }\n }\n }\n }\n\n /**\n * 执行 beforeDevServer 钩子\n */\n async runBeforeDevServer(): Promise<void> {\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.beforeDevServer) {\n try {\n await hooks.beforeDevServer(this.context);\n } catch (error) {\n this.context.logger.error(`插件 ${name} beforeDevServer 执行失败: ${error}`);\n }\n }\n }\n }\n\n /**\n * 执行 afterDevServer 钩子\n */\n async runAfterDevServer(server: { port: number; host: string }): Promise<void> {\n for (const [name, { hooks }] of this.plugins) {\n if (hooks.afterDevServer) {\n try {\n await hooks.afterDevServer(this.context, server);\n } catch (error) {\n this.context.logger.error(`插件 ${name} afterDevServer 执行失败: ${error}`);\n }\n }\n }\n }\n\n /**\n * 获取所有已加载的插件名称\n */\n getPluginNames(): string[] {\n return Array.from(this.plugins.keys());\n }\n\n /**\n * 获取所有已加载的插件\n */\n getPlugins(): YwkfPlugin[] {\n return Array.from(this.plugins.values()).map((p) => p.plugin);\n }\n\n /**\n * 获取所有已加载的插件钩子\n */\n getPluginHooks(): PluginHooks[] {\n return Array.from(this.plugins.values()).map((p) => p.hooks);\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/router/index.d.ts
CHANGED
|
@@ -4,34 +4,30 @@ import { Compiler } from '@rspack/core';
|
|
|
4
4
|
* 路由节点配置
|
|
5
5
|
*/
|
|
6
6
|
interface RouteConfig {
|
|
7
|
-
/** 路由路径 */
|
|
8
|
-
path: string;
|
|
9
|
-
/** 页面文件(page.tsx)相对路径 */
|
|
10
|
-
file?: string;
|
|
11
|
-
/** 布局文件(layout.tsx)相对路径 */
|
|
12
|
-
layoutFile?: string;
|
|
13
|
-
/** 错误边界文件(error.tsx)相对路径 */
|
|
14
|
-
errorFile?: string;
|
|
15
|
-
/** 加载状态文件(loading.tsx)相对路径 */
|
|
16
|
-
loadingFile?: string;
|
|
17
7
|
/** 通配路由文件($.tsx)相对路径 */
|
|
18
8
|
catchAllFile?: string;
|
|
19
|
-
/** 组件名称 */
|
|
20
|
-
name: string;
|
|
21
9
|
/** 子路由 */
|
|
22
10
|
children?: RouteConfig[];
|
|
11
|
+
/** 错误边界文件(error.tsx)相对路径 */
|
|
12
|
+
errorFile?: string;
|
|
13
|
+
/** 页面文件(page.tsx)相对路径 */
|
|
14
|
+
file?: string;
|
|
23
15
|
/** 是否为 index 路由 */
|
|
24
16
|
index?: boolean;
|
|
25
17
|
/** 是否为布局路由 */
|
|
26
18
|
isLayout?: boolean;
|
|
19
|
+
/** 布局文件(layout.tsx)相对路径 */
|
|
20
|
+
layoutFile?: string;
|
|
21
|
+
/** 加载状态文件(loading.tsx)相对路径 */
|
|
22
|
+
loadingFile?: string;
|
|
23
|
+
/** 组件名称 */
|
|
24
|
+
name: string;
|
|
25
|
+
/** 路由路径 */
|
|
26
|
+
path: string;
|
|
27
27
|
/** 是否为无路径布局(__prefix) */
|
|
28
28
|
pathless?: boolean;
|
|
29
29
|
}
|
|
30
30
|
interface GeneratorOptions {
|
|
31
|
-
/** 页面目录 */
|
|
32
|
-
pagesDir: string;
|
|
33
|
-
/** 输出目录 */
|
|
34
|
-
outputDir: string;
|
|
35
31
|
/** 路由 basename */
|
|
36
32
|
basename?: string;
|
|
37
33
|
/**
|
|
@@ -43,6 +39,10 @@ interface GeneratorOptions {
|
|
|
43
39
|
loading?: false | {
|
|
44
40
|
component: string;
|
|
45
41
|
};
|
|
42
|
+
/** 输出目录 */
|
|
43
|
+
outputDir: string;
|
|
44
|
+
/** 页面目录 */
|
|
45
|
+
pagesDir: string;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* Modern.js 风格约定式路由生成器
|
|
@@ -97,12 +97,12 @@ declare class ConventionalRouteGenerator {
|
|
|
97
97
|
declare function generateConventionalRoutes(options: GeneratorOptions): void;
|
|
98
98
|
|
|
99
99
|
interface ConventionalRoutePluginOptions {
|
|
100
|
-
/** 页面目录 */
|
|
101
|
-
pagesDir: string;
|
|
102
|
-
/** 输出目录 */
|
|
103
|
-
outputDir: string;
|
|
104
100
|
/** 路由 basename */
|
|
105
101
|
basename?: string;
|
|
102
|
+
/** 输出目录 */
|
|
103
|
+
outputDir: string;
|
|
104
|
+
/** 页面目录 */
|
|
105
|
+
pagesDir: string;
|
|
106
106
|
/** 是否监听文件变化(开发模式) */
|
|
107
107
|
watch?: boolean;
|
|
108
108
|
}
|
package/dist/router/index.js
CHANGED
|
@@ -6,7 +6,7 @@ function winPath(path) {
|
|
|
6
6
|
if (isExtendedLengthPath) {
|
|
7
7
|
return path;
|
|
8
8
|
}
|
|
9
|
-
return path.
|
|
9
|
+
return path.replaceAll("\\", "/");
|
|
10
10
|
}
|
|
11
11
|
var EXCLUDED_DIRS = /* @__PURE__ */ new Set([
|
|
12
12
|
"components",
|
|
@@ -142,16 +142,16 @@ var ConventionalRouteGenerator = class {
|
|
|
142
142
|
*/
|
|
143
143
|
resolveRoutePath(dirName, parentPath) {
|
|
144
144
|
let segment;
|
|
145
|
-
if (
|
|
145
|
+
if (/^\[\.\.\..+\]$/.test(dirName)) {
|
|
146
146
|
segment = "*";
|
|
147
|
-
} else if (
|
|
147
|
+
} else if (/^\[.+\$\]$/.test(dirName)) {
|
|
148
148
|
const param = dirName.slice(1, -2);
|
|
149
149
|
segment = `:${param}?`;
|
|
150
|
-
} else if (
|
|
150
|
+
} else if (/^\[.+\]$/.test(dirName)) {
|
|
151
151
|
const param = dirName.slice(1, -1);
|
|
152
152
|
segment = `:${param}`;
|
|
153
153
|
} else if (dirName.includes(".")) {
|
|
154
|
-
segment = dirName.
|
|
154
|
+
segment = dirName.replaceAll(".", "/");
|
|
155
155
|
} else {
|
|
156
156
|
segment = dirName;
|
|
157
157
|
}
|
|
@@ -162,7 +162,7 @@ var ConventionalRouteGenerator = class {
|
|
|
162
162
|
*/
|
|
163
163
|
generateRouteName(path) {
|
|
164
164
|
const name = path.split("/").filter(Boolean).map((s) => s.replace(/^:/, "Param").replace(/\?$/, "Optional").replace(/^\*$/, "CatchAll")).map((s) => {
|
|
165
|
-
const cleaned = s.
|
|
165
|
+
const cleaned = s.replaceAll(/[^a-z0-9]/gi, "");
|
|
166
166
|
if (!cleaned) return "";
|
|
167
167
|
return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
|
|
168
168
|
}).join("");
|
|
@@ -282,9 +282,7 @@ export default routes;
|
|
|
282
282
|
);
|
|
283
283
|
}
|
|
284
284
|
if (route.errorFile) {
|
|
285
|
-
errorImports.push(
|
|
286
|
-
`import ${name}Error from "@/pages/${toImportPath(route.errorFile)}";`
|
|
287
|
-
);
|
|
285
|
+
errorImports.push(`import ${name}Error from "@/pages/${toImportPath(route.errorFile)}";`);
|
|
288
286
|
}
|
|
289
287
|
if (route.loadingFile) {
|
|
290
288
|
loadingImports.push(
|
|
@@ -405,7 +403,7 @@ var ConventionalRoutePlugin = class {
|
|
|
405
403
|
* 标准化内容(去掉时间戳等动态部分)
|
|
406
404
|
*/
|
|
407
405
|
normalizeContent(content) {
|
|
408
|
-
return content.
|
|
406
|
+
return content.replaceAll(/\/\/ Generated at: .+/g, "");
|
|
409
407
|
}
|
|
410
408
|
/**
|
|
411
409
|
* 监听页面目录变化
|
package/dist/router/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/router/generator.ts","../../src/router/plugin.ts"],"sourcesContent":["import { existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from \"fs\";\nimport { join, relative } from \"path\";\n\n/** 将 Windows 路径统一为 POSIX 正斜杠(import 路径必须用 /) */\nfunction winPath(path: string): string {\n const isExtendedLengthPath = /^\\\\\\\\\\?\\\\/.test(path);\n if (isExtendedLengthPath) {\n return path;\n }\n return path.replace(/\\\\/g, \"/\");\n}\n\n/**\n * 路由节点配置\n */\nexport interface RouteConfig {\n /** 路由路径 */\n path: string;\n /** 页面文件(page.tsx)相对路径 */\n file?: string;\n /** 布局文件(layout.tsx)相对路径 */\n layoutFile?: string;\n /** 错误边界文件(error.tsx)相对路径 */\n errorFile?: string;\n /** 加载状态文件(loading.tsx)相对路径 */\n loadingFile?: string;\n /** 通配路由文件($.tsx)相对路径 */\n catchAllFile?: string;\n /** 组件名称 */\n name: string;\n /** 子路由 */\n children?: RouteConfig[];\n /** 是否为 index 路由 */\n index?: boolean;\n /** 是否为布局路由 */\n isLayout?: boolean;\n /** 是否为无路径布局(__prefix) */\n pathless?: boolean;\n}\n\nexport interface GeneratorOptions {\n /** 页面目录 */\n pagesDir: string;\n /** 输出目录 */\n outputDir: string;\n /** 路由 basename */\n basename?: string;\n /**\n * 加载状态配置\n * - `false`:禁用全局默认加载状态(Suspense fallback 为 null,但仍可通过 loading.tsx 覆盖)\n * - `{ component: string }`:自定义默认加载组件的导入路径,例如 `\"@/components/Loading\"`\n * - `undefined`:使用内置默认加载组件\n */\n loading?: false | { component: string };\n}\n\n/**\n * 不参与路由扫描的目录名\n */\nconst EXCLUDED_DIRS = new Set([\n \"components\",\n \"hooks\",\n \"utils\",\n \"services\",\n \"models\",\n \"assets\",\n \"types\",\n \"constants\",\n \"styles\",\n]);\n\n/**\n * 约定文件名匹配\n */\nconst CONVENTION_FILES = {\n page: /^page\\.(tsx?|jsx?)$/,\n layout: /^layout\\.(tsx?|jsx?)$/,\n error: /^error\\.(tsx?|jsx?)$/,\n loading: /^loading\\.(tsx?|jsx?)$/,\n catchAll: /^\\$\\.(tsx?|jsx?)$/,\n};\n\n/**\n * Modern.js 风格约定式路由生成器\n *\n * 文件约定:\n * - page.tsx — 页面内容(叶子组件)\n * - layout.tsx — 布局组件(使用 <Outlet> 渲染子路由)\n * - error.tsx — 错误边界组件\n * - loading.tsx — 加载状态组件\n * - $.tsx — 通配/404 路由\n *\n * 目录约定:\n * - [id]/ — 动态路由 → /:id\n * - [id$]/ — 可选动态路由 → /:id?\n * - [...slug]/ — 全匹配路由 → /*\n * - __auth/ — 无路径布局(不生成 URL 片段)\n * - user.profile/ — 扁平路由(. 分隔 → /user/profile)\n */\nexport class ConventionalRouteGenerator {\n private options: GeneratorOptions;\n\n constructor(options: GeneratorOptions) {\n this.options = options;\n }\n\n generate(): RouteConfig[] {\n const { pagesDir } = this.options;\n if (!existsSync(pagesDir)) {\n console.warn(`[ywkf] 页面目录不存在: ${pagesDir}`);\n return [];\n }\n return this.scanDirectory(pagesDir, \"/\");\n }\n\n /**\n * 扫描目录,生成路由树\n */\n private scanDirectory(dir: string, routePath: string): RouteConfig[] {\n const entries = readdirSync(dir);\n\n // 查找约定文件\n const layoutFile = entries.find((e) => CONVENTION_FILES.layout.test(e));\n const pageFile = entries.find((e) => CONVENTION_FILES.page.test(e));\n const errorFile = entries.find((e) => CONVENTION_FILES.error.test(e));\n const loadingFile = entries.find((e) => CONVENTION_FILES.loading.test(e));\n const catchAllFile = entries.find((e) => CONVENTION_FILES.catchAll.test(e));\n\n // 收集子目录\n const subDirs = entries.filter((e) => {\n if (e.startsWith(\".\")) return false;\n if (EXCLUDED_DIRS.has(e)) return false;\n return statSync(join(dir, e)).isDirectory();\n });\n\n // 递归子目录\n const childRoutes: RouteConfig[] = [];\n for (const subDir of subDirs) {\n const subDirPath = join(dir, subDir);\n\n // __prefix:无路径布局\n if (subDir.startsWith(\"__\")) {\n const pathlessRoutes = this.scanDirectory(subDirPath, routePath);\n // 如果该无路径目录有 layout,将子路由包装在其中\n const pathlessLayout = readdirSync(subDirPath).find((e) => CONVENTION_FILES.layout.test(e));\n if (pathlessLayout) {\n const pathlessChildren = this.scanDirectory(subDirPath, routePath);\n const pathlessLayoutRel = winPath(\n relative(this.options.pagesDir, join(subDirPath, pathlessLayout)),\n );\n childRoutes.push({\n path: routePath,\n name: this.generateRouteName(subDir.slice(2)),\n layoutFile: pathlessLayoutRel,\n isLayout: true,\n pathless: true,\n children: pathlessChildren.filter((r) => r.layoutFile !== pathlessLayoutRel),\n });\n } else {\n childRoutes.push(...pathlessRoutes);\n }\n continue;\n }\n\n // 计算路由路径\n const subRoutePath = this.resolveRoutePath(subDir, routePath);\n childRoutes.push(...this.scanDirectory(subDirPath, subRoutePath));\n }\n\n // 构建当前目录的路由节点\n const routeName = this.generateRouteName(routePath);\n const relPath = (file: string) => winPath(relative(this.options.pagesDir, join(dir, file)));\n\n // 有 layout.tsx → 创建布局路由节点,children 为子路由\n if (layoutFile) {\n const layoutChildren: RouteConfig[] = [];\n\n // page.tsx 作为 index 子路由\n if (pageFile) {\n layoutChildren.push({\n path: routePath,\n file: relPath(pageFile),\n name: `${routeName}Index`,\n index: true,\n });\n }\n\n // 通配路由\n if (catchAllFile) {\n layoutChildren.push({\n path: \"*\",\n file: relPath(catchAllFile),\n name: `${routeName}CatchAll`,\n });\n }\n\n layoutChildren.push(...childRoutes);\n\n return [\n {\n path: routePath,\n layoutFile: relPath(layoutFile),\n errorFile: errorFile ? relPath(errorFile) : undefined,\n loadingFile: loadingFile ? relPath(loadingFile) : undefined,\n name: routeName,\n isLayout: true,\n children: layoutChildren,\n },\n ];\n }\n\n // 无 layout → page.tsx 是叶子页面\n const result: RouteConfig[] = [];\n\n if (pageFile) {\n result.push({\n path: routePath,\n file: relPath(pageFile),\n errorFile: errorFile ? relPath(errorFile) : undefined,\n name: routeName,\n });\n }\n\n if (catchAllFile) {\n result.push({\n path: \"*\",\n file: relPath(catchAllFile),\n name: `${routeName}CatchAll`,\n });\n }\n\n result.push(...childRoutes);\n return result;\n }\n\n /**\n * 解析目录名到路由路径\n *\n * - [id] → :id\n * - [id$] → :id?\n * - [...slug] → *\n * - user.profile → user/profile\n */\n private resolveRoutePath(dirName: string, parentPath: string): string {\n let segment: string;\n\n // [...slug] → *\n if (dirName.match(/^\\[\\.\\.\\.(.+)\\]$/)) {\n segment = \"*\";\n }\n // [id$] → :id? (可选动态)\n else if (dirName.match(/^\\[(.+)\\$\\]$/)) {\n const param = dirName.slice(1, -2);\n segment = `:${param}?`;\n }\n // [id] → :id\n else if (dirName.match(/^\\[(.+)\\]$/)) {\n const param = dirName.slice(1, -1);\n segment = `:${param}`;\n }\n // user.profile → user/profile (扁平路由)\n else if (dirName.includes(\".\")) {\n segment = dirName.replace(/\\./g, \"/\");\n } else {\n segment = dirName;\n }\n\n return parentPath === \"/\" ? `/${segment}` : `${parentPath}/${segment}`;\n }\n\n /**\n * 生成有效的 JS 标识符名称\n */\n private generateRouteName(path: string): string {\n const name = path\n .split(\"/\")\n .filter(Boolean)\n .map((s) => s.replace(/^:/, \"Param\").replace(/\\?$/, \"Optional\").replace(/^\\*$/, \"CatchAll\"))\n .map((s) => {\n const cleaned = s.replace(/[^a-zA-Z0-9]/g, \"\");\n if (!cleaned) return \"\";\n return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);\n })\n .join(\"\");\n\n if (!name || /^\\d/.test(name)) {\n return `Page${name || \"Root\"}`;\n }\n return name;\n }\n\n // ===== 代码生成 =====\n\n generateCode(): string {\n const routes = this.generate();\n const lazyImports: string[] = [];\n const errorImports: string[] = [];\n const loadingImports: string[] = [];\n\n this.collectImports(routes, lazyImports, errorImports, loadingImports);\n\n const { loading } = this.options;\n const hasCustomLoading = loading && typeof loading === \"object\" && loading.component;\n const loadingDisabled = loading === false;\n\n let loadingSection: string;\n if (loadingDisabled) {\n loadingSection = `\n// 懒加载包装(加载状态已禁用)\nfunction LazyRoute({\n Component,\n Loading,\n}: {\n Component: React.LazyExoticComponent<React.ComponentType<unknown>>;\n Loading?: React.ComponentType;\n}) {\n const fallback = Loading ? <Loading /> : null;\n return (\n <Suspense fallback={fallback}>\n <Component />\n </Suspense>\n );\n}`;\n } else if (hasCustomLoading) {\n loadingSection = `\nimport CustomDefaultLoading from \"${loading.component}\";\n\n// 懒加载包装(使用自定义默认加载组件)\nfunction LazyRoute({\n Component,\n Loading = CustomDefaultLoading,\n}: {\n Component: React.LazyExoticComponent<React.ComponentType<unknown>>;\n Loading?: React.ComponentType;\n}) {\n return (\n <Suspense fallback={<Loading />}>\n <Component />\n </Suspense>\n );\n}`;\n } else {\n loadingSection = `\n// 默认加载状态\nconst DefaultLoading = () => <div style={{ padding: 24, textAlign: \"center\" }}>加载中...</div>;\n\n// 懒加载包装\nfunction LazyRoute({\n Component,\n Loading = DefaultLoading,\n}: {\n Component: React.LazyExoticComponent<React.ComponentType<unknown>>;\n Loading?: React.ComponentType;\n}) {\n return (\n <Suspense fallback={<Loading />}>\n <Component />\n </Suspense>\n );\n}`;\n }\n\n return `// 此文件由 @4399ywkf/core 自动生成,请勿手动修改\n// Generated at: ${new Date().toISOString()}\n\nimport React, { lazy, Suspense } from \"react\";\nimport { createBrowserRouter, type RouteObject } from \"react-router\";\nimport { RouteErrorBoundary } from \"@4399ywkf/core/runtime\";\n${errorImports.length > 0 ? `\\n// 同步错误边界组件\\n${errorImports.join(\"\\n\")}` : \"\"}\n\n// 懒加载页面组件\n${lazyImports.join(\"\\n\")}\n${loadingImports.length > 0 ? `\\n// 加载状态组件\\n${loadingImports.join(\"\\n\")}` : \"\"}\n${loadingSection}\n\n// 路由配置\nexport const routes: RouteObject[] = ${this.emitRouteArray(routes)};\n\n/**\n * 创建路由实例\n */\nexport function createRouter(basename?: string) {\n return createBrowserRouter(routes, { basename: basename || \"/\" });\n}\n\nexport default routes;\n`;\n }\n\n private collectImports(\n routes: RouteConfig[],\n lazyImports: string[],\n errorImports: string[],\n loadingImports: string[],\n ): void {\n for (const route of routes) {\n const name = route.name;\n const toImportPath = (f: string) => f.replace(/\\.(tsx?|jsx?)$/, \"\");\n\n if (route.isLayout && route.layoutFile) {\n lazyImports.push(\n `const ${name}Layout = lazy(() => import(\"@/pages/${toImportPath(route.layoutFile)}\"));`,\n );\n }\n if (route.file) {\n lazyImports.push(\n `const ${name}Page = lazy(() => import(\"@/pages/${toImportPath(route.file)}\"));`,\n );\n }\n if (route.errorFile) {\n errorImports.push(\n `import ${name}Error from \"@/pages/${toImportPath(route.errorFile)}\";`,\n );\n }\n if (route.loadingFile) {\n loadingImports.push(\n `const ${name}Loading = lazy(() => import(\"@/pages/${toImportPath(\n route.loadingFile,\n )}\"));`,\n );\n }\n\n if (route.children) {\n this.collectImports(route.children, lazyImports, errorImports, loadingImports);\n }\n }\n }\n\n private emitRouteArray(routes: RouteConfig[], parentPath?: string, depth = 0): string {\n const items = routes.map((r) => this.emitRouteObject(r, parentPath, depth));\n return `[\\n ${items.join(\",\\n \")}\\n]`;\n }\n\n private emitRouteObject(route: RouteConfig, parentPath: string | undefined, depth: number): string {\n const parts: string[] = [];\n const name = route.name;\n\n // path\n if (route.index) {\n parts.push(\"index: true\");\n } else if (route.pathless) {\n // 无路径布局不输出 path\n } else if (route.path === \"*\") {\n parts.push(`path: \"*\"`);\n } else if (parentPath && route.path.startsWith(parentPath) && parentPath !== \"/\") {\n const rel = route.path.slice(parentPath.length + 1);\n parts.push(`path: \"${rel || \"\"}\"`);\n } else {\n parts.push(`path: \"${route.path}\"`);\n }\n\n // element\n if (route.isLayout && route.layoutFile) {\n const loadingProp = route.loadingFile ? ` Loading={${name}Loading}` : \"\";\n parts.push(`element: <LazyRoute Component={${name}Layout}${loadingProp} />`);\n } else if (route.file) {\n parts.push(`element: <LazyRoute Component={${name}Page} />`);\n }\n\n // errorElement\n if (route.errorFile) {\n parts.push(`errorElement: <RouteErrorBoundary fallback={<${name}Error />} />`);\n } else if (depth === 0) {\n // React Router 会在内部接住 lazy route rejection;顶层必须有同步 errorElement 才能触发恢复。\n parts.push(`errorElement: <RouteErrorBoundary />`);\n }\n\n // children\n if (route.children && route.children.length > 0) {\n const childParent = route.pathless ? parentPath : route.path;\n parts.push(`children: ${this.emitRouteArray(route.children, childParent, depth + 1)}`);\n }\n\n return `{\\n ${parts.join(\",\\n \")}\\n }`;\n }\n\n /**\n * 写入路由文件\n */\n write(): void {\n const { outputDir } = this.options;\n const code = this.generateCode();\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n writeFileSync(join(outputDir, \"routes.tsx\"), code, \"utf-8\");\n if (process.env.DEBUG) console.log(`[ywkf] 约定式路由已生成`);\n }\n}\n\n/**\n * 生成约定式路由\n */\nexport function generateConventionalRoutes(options: GeneratorOptions): void {\n new ConventionalRouteGenerator(options).write();\n}\n","import type { Compiler } from \"@rspack/core\";\nimport { existsSync, watch } from \"fs\";\nimport { join } from \"path\";\nimport { ConventionalRouteGenerator } from \"./generator.js\";\n\nexport interface ConventionalRoutePluginOptions {\n /** 页面目录 */\n pagesDir: string;\n /** 输出目录 */\n outputDir: string;\n /** 路由 basename */\n basename?: string;\n /** 是否监听文件变化(开发模式) */\n watch?: boolean;\n}\n\n/**\n * 约定式路由 Rspack 插件\n *\n * 在编译开始前扫描 src/pages 目录,生成 .ywkf/routes.tsx\n */\nexport class ConventionalRoutePlugin {\n private options: ConventionalRoutePluginOptions;\n private isWatching = false;\n private hasGenerated = false;\n private lastGeneratedContent = \"\";\n\n constructor(options: ConventionalRoutePluginOptions) {\n this.options = options;\n }\n\n apply(compiler: Compiler): void {\n const pluginName = \"ConventionalRoutePlugin\";\n\n // 只在首次编译时生成路由\n compiler.hooks.beforeCompile.tapAsync(pluginName, (_params, callback) => {\n if (!this.hasGenerated) {\n this.generateRoutes();\n this.hasGenerated = true;\n }\n callback();\n });\n\n // 开发模式下监听文件变化\n if (this.options.watch && !this.isWatching) {\n this.watchPages(compiler);\n }\n }\n\n /**\n * 生成路由文件(带内容比对,避免不必要的重复生成)\n */\n private generateRoutes(): void {\n try {\n const generator = new ConventionalRouteGenerator({\n pagesDir: this.options.pagesDir,\n outputDir: this.options.outputDir,\n basename: this.options.basename,\n });\n\n const newContent = generator.generateCode();\n const _outputPath = join(this.options.outputDir, \"routes.tsx\");\n\n // 比对内容,如果相同则跳过(去掉时间戳后比较)\n const normalizedNew = this.normalizeContent(newContent);\n const normalizedOld = this.normalizeContent(this.lastGeneratedContent);\n\n if (normalizedNew === normalizedOld) {\n return; // 内容相同,跳过生成\n }\n\n generator.write();\n this.lastGeneratedContent = newContent;\n } catch (error) {\n console.error(\"[ywkf] 生成路由失败:\", error);\n }\n }\n\n /**\n * 标准化内容(去掉时间戳等动态部分)\n */\n private normalizeContent(content: string): string {\n return content.replace(/\\/\\/ Generated at: .+/g, \"\");\n }\n\n /**\n * 监听页面目录变化\n */\n private watchPages(compiler: Compiler): void {\n if (!existsSync(this.options.pagesDir)) {\n return;\n }\n\n this.isWatching = true;\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const watcher = watch(this.options.pagesDir, { recursive: true }, (_eventType, filename) => {\n // 只处理 tsx/jsx 文件\n if (!filename?.match(/\\.(tsx?|jsx?)$/)) {\n return;\n }\n\n // 防抖处理\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n\n debounceTimer = setTimeout(() => {\n if (process.env.DEBUG) console.log(`[ywkf] 检测到页面变化: ${filename}`);\n this.generateRoutes();\n }, 500);\n });\n\n // 编译器关闭时(含 dev 热重启)关闭监听,避免泄漏\n compiler.hooks.shutdown.tap(\"ConventionalRoutePlugin\", () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n watcher.close();\n // 重置实例状态,使该插件实例在新编译器上可被安全复用\n this.isWatching = false;\n this.hasGenerated = false;\n this.lastGeneratedContent = \"\";\n });\n }\n}\n"],"mappings":"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","names":["existsSync","join","join","existsSync"]}
|
|
1
|
+
{"version":3,"sources":["../../src/router/generator.ts","../../src/router/plugin.ts"],"sourcesContent":["import { existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n/** 将 Windows 路径统一为 POSIX 正斜杠(import 路径必须用 /) */\nfunction winPath(path: string): string {\n const isExtendedLengthPath = /^\\\\\\\\\\?\\\\/.test(path);\n if (isExtendedLengthPath) {\n return path;\n }\n return path.replaceAll('\\\\', '/');\n}\n\n/**\n * 路由节点配置\n */\nexport interface RouteConfig {\n /** 通配路由文件($.tsx)相对路径 */\n catchAllFile?: string;\n /** 子路由 */\n children?: RouteConfig[];\n /** 错误边界文件(error.tsx)相对路径 */\n errorFile?: string;\n /** 页面文件(page.tsx)相对路径 */\n file?: string;\n /** 是否为 index 路由 */\n index?: boolean;\n /** 是否为布局路由 */\n isLayout?: boolean;\n /** 布局文件(layout.tsx)相对路径 */\n layoutFile?: string;\n /** 加载状态文件(loading.tsx)相对路径 */\n loadingFile?: string;\n /** 组件名称 */\n name: string;\n /** 路由路径 */\n path: string;\n /** 是否为无路径布局(__prefix) */\n pathless?: boolean;\n}\n\nexport interface GeneratorOptions {\n /** 路由 basename */\n basename?: string;\n /**\n * 加载状态配置\n * - `false`:禁用全局默认加载状态(Suspense fallback 为 null,但仍可通过 loading.tsx 覆盖)\n * - `{ component: string }`:自定义默认加载组件的导入路径,例如 `\"@/components/Loading\"`\n * - `undefined`:使用内置默认加载组件\n */\n loading?: false | { component: string };\n /** 输出目录 */\n outputDir: string;\n /** 页面目录 */\n pagesDir: string;\n}\n\n/**\n * 不参与路由扫描的目录名\n */\nconst EXCLUDED_DIRS = new Set([\n 'components',\n 'hooks',\n 'utils',\n 'services',\n 'models',\n 'assets',\n 'types',\n 'constants',\n 'styles',\n]);\n\n/**\n * 约定文件名匹配\n */\nconst CONVENTION_FILES = {\n page: /^page\\.(tsx?|jsx?)$/,\n layout: /^layout\\.(tsx?|jsx?)$/,\n error: /^error\\.(tsx?|jsx?)$/,\n loading: /^loading\\.(tsx?|jsx?)$/,\n catchAll: /^\\$\\.(tsx?|jsx?)$/,\n};\n\n/**\n * Modern.js 风格约定式路由生成器\n *\n * 文件约定:\n * - page.tsx — 页面内容(叶子组件)\n * - layout.tsx — 布局组件(使用 <Outlet> 渲染子路由)\n * - error.tsx — 错误边界组件\n * - loading.tsx — 加载状态组件\n * - $.tsx — 通配/404 路由\n *\n * 目录约定:\n * - [id]/ — 动态路由 → /:id\n * - [id$]/ — 可选动态路由 → /:id?\n * - [...slug]/ — 全匹配路由 → /*\n * - __auth/ — 无路径布局(不生成 URL 片段)\n * - user.profile/ — 扁平路由(. 分隔 → /user/profile)\n */\nexport class ConventionalRouteGenerator {\n private options: GeneratorOptions;\n\n constructor(options: GeneratorOptions) {\n this.options = options;\n }\n\n generate(): RouteConfig[] {\n const { pagesDir } = this.options;\n if (!existsSync(pagesDir)) {\n console.warn(`[ywkf] 页面目录不存在: ${pagesDir}`);\n return [];\n }\n return this.scanDirectory(pagesDir, '/');\n }\n\n /**\n * 扫描目录,生成路由树\n */\n private scanDirectory(dir: string, routePath: string): RouteConfig[] {\n const entries = readdirSync(dir);\n\n // 查找约定文件\n const layoutFile = entries.find((e) => CONVENTION_FILES.layout.test(e));\n const pageFile = entries.find((e) => CONVENTION_FILES.page.test(e));\n const errorFile = entries.find((e) => CONVENTION_FILES.error.test(e));\n const loadingFile = entries.find((e) => CONVENTION_FILES.loading.test(e));\n const catchAllFile = entries.find((e) => CONVENTION_FILES.catchAll.test(e));\n\n // 收集子目录\n const subDirs = entries.filter((e) => {\n if (e.startsWith('.')) return false;\n if (EXCLUDED_DIRS.has(e)) return false;\n return statSync(join(dir, e)).isDirectory();\n });\n\n // 递归子目录\n const childRoutes: RouteConfig[] = [];\n for (const subDir of subDirs) {\n const subDirPath = join(dir, subDir);\n\n // __prefix:无路径布局\n if (subDir.startsWith('__')) {\n const pathlessRoutes = this.scanDirectory(subDirPath, routePath);\n // 如果该无路径目录有 layout,将子路由包装在其中\n const pathlessLayout = readdirSync(subDirPath).find((e) => CONVENTION_FILES.layout.test(e));\n if (pathlessLayout) {\n const pathlessChildren = this.scanDirectory(subDirPath, routePath);\n const pathlessLayoutRel = winPath(\n relative(this.options.pagesDir, join(subDirPath, pathlessLayout)),\n );\n childRoutes.push({\n path: routePath,\n name: this.generateRouteName(subDir.slice(2)),\n layoutFile: pathlessLayoutRel,\n isLayout: true,\n pathless: true,\n children: pathlessChildren.filter((r) => r.layoutFile !== pathlessLayoutRel),\n });\n } else {\n childRoutes.push(...pathlessRoutes);\n }\n continue;\n }\n\n // 计算路由路径\n const subRoutePath = this.resolveRoutePath(subDir, routePath);\n childRoutes.push(...this.scanDirectory(subDirPath, subRoutePath));\n }\n\n // 构建当前目录的路由节点\n const routeName = this.generateRouteName(routePath);\n const relPath = (file: string) => winPath(relative(this.options.pagesDir, join(dir, file)));\n\n // 有 layout.tsx → 创建布局路由节点,children 为子路由\n if (layoutFile) {\n const layoutChildren: RouteConfig[] = [];\n\n // page.tsx 作为 index 子路由\n if (pageFile) {\n layoutChildren.push({\n path: routePath,\n file: relPath(pageFile),\n name: `${routeName}Index`,\n index: true,\n });\n }\n\n // 通配路由\n if (catchAllFile) {\n layoutChildren.push({\n path: '*',\n file: relPath(catchAllFile),\n name: `${routeName}CatchAll`,\n });\n }\n\n layoutChildren.push(...childRoutes);\n\n return [\n {\n path: routePath,\n layoutFile: relPath(layoutFile),\n errorFile: errorFile ? relPath(errorFile) : undefined,\n loadingFile: loadingFile ? relPath(loadingFile) : undefined,\n name: routeName,\n isLayout: true,\n children: layoutChildren,\n },\n ];\n }\n\n // 无 layout → page.tsx 是叶子页面\n const result: RouteConfig[] = [];\n\n if (pageFile) {\n result.push({\n path: routePath,\n file: relPath(pageFile),\n errorFile: errorFile ? relPath(errorFile) : undefined,\n name: routeName,\n });\n }\n\n if (catchAllFile) {\n result.push({\n path: '*',\n file: relPath(catchAllFile),\n name: `${routeName}CatchAll`,\n });\n }\n\n result.push(...childRoutes);\n return result;\n }\n\n /**\n * 解析目录名到路由路径\n *\n * - [id] → :id\n * - [id$] → :id?\n * - [...slug] → *\n * - user.profile → user/profile\n */\n private resolveRoutePath(dirName: string, parentPath: string): string {\n let segment: string;\n\n // [...slug] → *\n if (/^\\[\\.\\.\\..+\\]$/.test(dirName)) {\n segment = '*';\n }\n // [id$] → :id? (可选动态)\n else if (/^\\[.+\\$\\]$/.test(dirName)) {\n const param = dirName.slice(1, -2);\n segment = `:${param}?`;\n }\n // [id] → :id\n else if (/^\\[.+\\]$/.test(dirName)) {\n const param = dirName.slice(1, -1);\n segment = `:${param}`;\n }\n // user.profile → user/profile (扁平路由)\n else if (dirName.includes('.')) {\n segment = dirName.replaceAll('.', '/');\n } else {\n segment = dirName;\n }\n\n return parentPath === '/' ? `/${segment}` : `${parentPath}/${segment}`;\n }\n\n /**\n * 生成有效的 JS 标识符名称\n */\n private generateRouteName(path: string): string {\n const name = path\n .split('/')\n .filter(Boolean)\n .map((s) => s.replace(/^:/, 'Param').replace(/\\?$/, 'Optional').replace(/^\\*$/, 'CatchAll'))\n .map((s) => {\n const cleaned = s.replaceAll(/[^a-z0-9]/gi, '');\n if (!cleaned) return '';\n return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);\n })\n .join('');\n\n if (!name || /^\\d/.test(name)) {\n return `Page${name || 'Root'}`;\n }\n return name;\n }\n\n // ===== 代码生成 =====\n\n generateCode(): string {\n const routes = this.generate();\n const lazyImports: string[] = [];\n const errorImports: string[] = [];\n const loadingImports: string[] = [];\n\n this.collectImports(routes, lazyImports, errorImports, loadingImports);\n\n const { loading } = this.options;\n const hasCustomLoading = loading && typeof loading === 'object' && loading.component;\n const loadingDisabled = loading === false;\n\n let loadingSection: string;\n if (loadingDisabled) {\n loadingSection = `\n// 懒加载包装(加载状态已禁用)\nfunction LazyRoute({\n Component,\n Loading,\n}: {\n Component: React.LazyExoticComponent<React.ComponentType<unknown>>;\n Loading?: React.ComponentType;\n}) {\n const fallback = Loading ? <Loading /> : null;\n return (\n <Suspense fallback={fallback}>\n <Component />\n </Suspense>\n );\n}`;\n } else if (hasCustomLoading) {\n loadingSection = `\nimport CustomDefaultLoading from \"${loading.component}\";\n\n// 懒加载包装(使用自定义默认加载组件)\nfunction LazyRoute({\n Component,\n Loading = CustomDefaultLoading,\n}: {\n Component: React.LazyExoticComponent<React.ComponentType<unknown>>;\n Loading?: React.ComponentType;\n}) {\n return (\n <Suspense fallback={<Loading />}>\n <Component />\n </Suspense>\n );\n}`;\n } else {\n loadingSection = `\n// 默认加载状态\nconst DefaultLoading = () => <div style={{ padding: 24, textAlign: \"center\" }}>加载中...</div>;\n\n// 懒加载包装\nfunction LazyRoute({\n Component,\n Loading = DefaultLoading,\n}: {\n Component: React.LazyExoticComponent<React.ComponentType<unknown>>;\n Loading?: React.ComponentType;\n}) {\n return (\n <Suspense fallback={<Loading />}>\n <Component />\n </Suspense>\n );\n}`;\n }\n\n return `// 此文件由 @4399ywkf/core 自动生成,请勿手动修改\n// Generated at: ${new Date().toISOString()}\n\nimport React, { lazy, Suspense } from \"react\";\nimport { createBrowserRouter, type RouteObject } from \"react-router\";\nimport { RouteErrorBoundary } from \"@4399ywkf/core/runtime\";\n${errorImports.length > 0 ? `\\n// 同步错误边界组件\\n${errorImports.join('\\n')}` : ''}\n\n// 懒加载页面组件\n${lazyImports.join('\\n')}\n${loadingImports.length > 0 ? `\\n// 加载状态组件\\n${loadingImports.join('\\n')}` : ''}\n${loadingSection}\n\n// 路由配置\nexport const routes: RouteObject[] = ${this.emitRouteArray(routes)};\n\n/**\n * 创建路由实例\n */\nexport function createRouter(basename?: string) {\n return createBrowserRouter(routes, { basename: basename || \"/\" });\n}\n\nexport default routes;\n`;\n }\n\n private collectImports(\n routes: RouteConfig[],\n lazyImports: string[],\n errorImports: string[],\n loadingImports: string[],\n ): void {\n for (const route of routes) {\n const name = route.name;\n const toImportPath = (f: string) => f.replace(/\\.(tsx?|jsx?)$/, '');\n\n if (route.isLayout && route.layoutFile) {\n lazyImports.push(\n `const ${name}Layout = lazy(() => import(\"@/pages/${toImportPath(route.layoutFile)}\"));`,\n );\n }\n if (route.file) {\n lazyImports.push(\n `const ${name}Page = lazy(() => import(\"@/pages/${toImportPath(route.file)}\"));`,\n );\n }\n if (route.errorFile) {\n errorImports.push(`import ${name}Error from \"@/pages/${toImportPath(route.errorFile)}\";`);\n }\n if (route.loadingFile) {\n loadingImports.push(\n `const ${name}Loading = lazy(() => import(\"@/pages/${toImportPath(\n route.loadingFile,\n )}\"));`,\n );\n }\n\n if (route.children) {\n this.collectImports(route.children, lazyImports, errorImports, loadingImports);\n }\n }\n }\n\n private emitRouteArray(routes: RouteConfig[], parentPath?: string, depth = 0): string {\n const items = routes.map((r) => this.emitRouteObject(r, parentPath, depth));\n return `[\\n ${items.join(',\\n ')}\\n]`;\n }\n\n private emitRouteObject(\n route: RouteConfig,\n parentPath: string | undefined,\n depth: number,\n ): string {\n const parts: string[] = [];\n const name = route.name;\n\n // path\n if (route.index) {\n parts.push('index: true');\n } else if (route.pathless) {\n // 无路径布局不输出 path\n } else if (route.path === '*') {\n parts.push(`path: \"*\"`);\n } else if (parentPath && route.path.startsWith(parentPath) && parentPath !== '/') {\n const rel = route.path.slice(parentPath.length + 1);\n parts.push(`path: \"${rel || ''}\"`);\n } else {\n parts.push(`path: \"${route.path}\"`);\n }\n\n // element\n if (route.isLayout && route.layoutFile) {\n const loadingProp = route.loadingFile ? ` Loading={${name}Loading}` : '';\n parts.push(`element: <LazyRoute Component={${name}Layout}${loadingProp} />`);\n } else if (route.file) {\n parts.push(`element: <LazyRoute Component={${name}Page} />`);\n }\n\n // errorElement\n if (route.errorFile) {\n parts.push(`errorElement: <RouteErrorBoundary fallback={<${name}Error />} />`);\n } else if (depth === 0) {\n // React Router 会在内部接住 lazy route rejection;顶层必须有同步 errorElement 才能触发恢复。\n parts.push(`errorElement: <RouteErrorBoundary />`);\n }\n\n // children\n if (route.children && route.children.length > 0) {\n const childParent = route.pathless ? parentPath : route.path;\n parts.push(`children: ${this.emitRouteArray(route.children, childParent, depth + 1)}`);\n }\n\n return `{\\n ${parts.join(',\\n ')}\\n }`;\n }\n\n /**\n * 写入路由文件\n */\n write(): void {\n const { outputDir } = this.options;\n const code = this.generateCode();\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n writeFileSync(join(outputDir, 'routes.tsx'), code, 'utf-8');\n if (process.env.DEBUG) console.log(`[ywkf] 约定式路由已生成`);\n }\n}\n\n/**\n * 生成约定式路由\n */\nexport function generateConventionalRoutes(options: GeneratorOptions): void {\n new ConventionalRouteGenerator(options).write();\n}\n","import { existsSync, watch } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { Compiler } from '@rspack/core';\n\nimport { ConventionalRouteGenerator } from './generator.js';\n\nexport interface ConventionalRoutePluginOptions {\n /** 路由 basename */\n basename?: string;\n /** 输出目录 */\n outputDir: string;\n /** 页面目录 */\n pagesDir: string;\n /** 是否监听文件变化(开发模式) */\n watch?: boolean;\n}\n\n/**\n * 约定式路由 Rspack 插件\n *\n * 在编译开始前扫描 src/pages 目录,生成 .ywkf/routes.tsx\n */\nexport class ConventionalRoutePlugin {\n private options: ConventionalRoutePluginOptions;\n private isWatching = false;\n private hasGenerated = false;\n private lastGeneratedContent = '';\n\n constructor(options: ConventionalRoutePluginOptions) {\n this.options = options;\n }\n\n apply(compiler: Compiler): void {\n const pluginName = 'ConventionalRoutePlugin';\n\n // 只在首次编译时生成路由\n compiler.hooks.beforeCompile.tapAsync(pluginName, (_params, callback) => {\n if (!this.hasGenerated) {\n this.generateRoutes();\n this.hasGenerated = true;\n }\n callback();\n });\n\n // 开发模式下监听文件变化\n if (this.options.watch && !this.isWatching) {\n this.watchPages(compiler);\n }\n }\n\n /**\n * 生成路由文件(带内容比对,避免不必要的重复生成)\n */\n private generateRoutes(): void {\n try {\n const generator = new ConventionalRouteGenerator({\n pagesDir: this.options.pagesDir,\n outputDir: this.options.outputDir,\n basename: this.options.basename,\n });\n\n const newContent = generator.generateCode();\n const _outputPath = join(this.options.outputDir, 'routes.tsx');\n\n // 比对内容,如果相同则跳过(去掉时间戳后比较)\n const normalizedNew = this.normalizeContent(newContent);\n const normalizedOld = this.normalizeContent(this.lastGeneratedContent);\n\n if (normalizedNew === normalizedOld) {\n return; // 内容相同,跳过生成\n }\n\n generator.write();\n this.lastGeneratedContent = newContent;\n } catch (error) {\n console.error('[ywkf] 生成路由失败:', error);\n }\n }\n\n /**\n * 标准化内容(去掉时间戳等动态部分)\n */\n private normalizeContent(content: string): string {\n return content.replaceAll(/\\/\\/ Generated at: .+/g, '');\n }\n\n /**\n * 监听页面目录变化\n */\n private watchPages(compiler: Compiler): void {\n if (!existsSync(this.options.pagesDir)) {\n return;\n }\n\n this.isWatching = true;\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const watcher = watch(this.options.pagesDir, { recursive: true }, (_eventType, filename) => {\n // 只处理 tsx/jsx 文件\n if (!filename?.match(/\\.(tsx?|jsx?)$/)) {\n return;\n }\n\n // 防抖处理\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n\n debounceTimer = setTimeout(() => {\n if (process.env.DEBUG) console.log(`[ywkf] 检测到页面变化: ${filename}`);\n this.generateRoutes();\n }, 500);\n });\n\n // 编译器关闭时(含 dev 热重启)关闭监听,避免泄漏\n compiler.hooks.shutdown.tap('ConventionalRoutePlugin', () => {\n if (debounceTimer) clearTimeout(debounceTimer);\n watcher.close();\n // 重置实例状态,使该插件实例在新编译器上可被安全复用\n this.isWatching = false;\n this.hasGenerated = false;\n this.lastGeneratedContent = '';\n });\n }\n}\n"],"mappings":"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","names":["existsSync","join","join","existsSync"]}
|
package/dist/rspack/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Configuration } from '@rspack/core';
|
|
2
|
-
import { Y as YwkfConfig } from '../schema-
|
|
3
|
-
import '../types-
|
|
2
|
+
import { Y as YwkfConfig } from '../schema-BblOKuYl.js';
|
|
3
|
+
import '../types-DZ7Nz9bQ.js';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'react-router';
|
|
6
6
|
|