@4399ywkf/core 5.0.27 → 5.0.29
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/dist/cli/index.js +2225 -108
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +24 -4
- package/dist/config/index.js +2124 -6
- package/dist/config/index.js.map +1 -1
- package/dist/index.d.ts +5 -475
- package/dist/index.js +4291 -3860
- package/dist/index.js.map +1 -1
- package/dist/plugin/index.d.ts +3 -3
- package/dist/rspack/index.d.ts +2 -2
- package/dist/rspack/index.js +2129 -72
- package/dist/rspack/index.js.map +1 -1
- package/dist/runtime/index.d.ts +2 -2
- package/dist/schema-CMyZyL6E.d.ts +1153 -0
- package/dist/{types-DbUq-VY8.d.ts → types-BYqzyGAY.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/schema-runIYOB7.d.ts +0 -407
package/dist/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/loader.ts","../../src/config/schema.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { extname, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport deepmerge from \"deepmerge\";\nimport { defaultConfig, type YwkfConfig } from \"./schema.js\";\n\n/** 支持的配置文件名 */\nconst CONFIG_FILES = [\"ywkf.config.ts\", \"ywkf.config.mts\", \"ywkf.config.js\", \"ywkf.config.mjs\"];\n\n/**\n * 查找配置文件\n */\nexport function findConfigFile(cwd: string): string | null {\n for (const file of CONFIG_FILES) {\n const configPath = resolve(cwd, file);\n if (existsSync(configPath)) {\n return configPath;\n }\n }\n return null;\n}\n\n/**\n * 加载 TypeScript 配置文件\n */\nasync function loadTsConfig(configPath: string): Promise<YwkfConfig> {\n const jiti = (await import(\"jiti\")).default;\n const loader = jiti(configPath, {\n interopDefault: true,\n });\n\n const config = loader(configPath);\n return config.default || config;\n}\n\n/**\n * 加载 JavaScript 配置文件\n */\nasync function loadJsConfig(configPath: string): Promise<YwkfConfig> {\n const fileUrl = pathToFileURL(configPath).href;\n const module = await import(fileUrl);\n return module.default || module;\n}\n\n/**\n * 加载配置文件\n */\nexport async function loadConfigFile(configPath: string): Promise<YwkfConfig> {\n const ext = extname(configPath);\n\n if (ext === \".ts\" || ext === \".mts\") {\n return loadTsConfig(configPath);\n }\n\n return loadJsConfig(configPath);\n}\n\n/**\n * 合并配置\n */\nexport function mergeConfig(\n userConfig: YwkfConfig,\n baseConfig: YwkfConfig = defaultConfig,\n): Required<YwkfConfig> {\n return deepmerge(baseConfig, userConfig, {\n arrayMerge: (_, sourceArray) => sourceArray,\n }) as Required<YwkfConfig>;\n}\n\n/**\n * 解析并加载完整配置\n * @param cwd 工作目录\n * @returns 合并后的完整配置\n */\nexport async function resolveConfig(cwd: string): Promise<{\n config: Required<YwkfConfig>;\n configPath: string | null;\n}> {\n const configPath = findConfigFile(cwd);\n\n if (!configPath) {\n console.warn(\"⚠️ 未找到配置文件 (ywkf.config.ts),使用默认配置\");\n return {\n config: defaultConfig as Required<YwkfConfig>,\n configPath: null,\n };\n }\n\n try {\n const userConfig = await loadConfigFile(configPath);\n const config = mergeConfig(userConfig);\n\n return { config, configPath };\n } catch (error) {\n console.error(\"❌ 配置文件加载失败:\", error);\n throw error;\n }\n}\n\n/**\n * 获取应用路径解析器\n */\nexport function createPathResolver(cwd: string) {\n return {\n resolveApp: (relativePath: string) => resolve(cwd, relativePath),\n cwd,\n };\n}\n","import type { Configuration as RspackConfig } from \"@rspack/core\";\nimport type { PluginConfig } from \"../plugin/types.js\";\n\n/**\n * 开发服务器配置\n */\nexport interface DevServerConfig {\n /** 开发服务器端口 */\n port?: number;\n /** 开发服务器主机 */\n host?: string;\n /** 代理配置 */\n proxy?: Record<string, string | object>;\n /** 是否开启 HTTPS */\n https?: boolean;\n}\n\n/**\n * 输出配置\n */\nexport interface OutputConfig {\n /** 输出目录 */\n path?: string;\n /** 公共路径 */\n publicPath?: string;\n /** 是否清理输出目录 */\n clean?: boolean;\n}\n\n/**\n * HTML 配置\n */\nexport interface HtmlConfig {\n /** 页面标题 */\n title?: string;\n /** HTML 模板路径 */\n template?: string;\n /** favicon 路径 */\n favicon?: string;\n /** 挂载根元素 ID */\n mountRoot?: string;\n}\n\n/**\n * 样式配置\n */\nexport interface StyleConfig {\n /** 是否启用 CSS Modules */\n cssModules?: boolean;\n /** Less 配置 */\n less?: {\n /** 是否启用 */\n enabled?: boolean;\n /** Less 选项 */\n lessOptions?: Record<string, unknown>;\n };\n /** Sass 配置 */\n sass?: {\n /** 是否启用 */\n enabled?: boolean;\n /** Sass 选项 */\n sassOptions?: Record<string, unknown>;\n };\n /** 是否启用 TailwindCSS */\n tailwindcss?: boolean;\n}\n\n/**\n * 路由配置\n */\nexport interface RouterConfig {\n /** 路由基础路径 */\n basename?: string;\n /** 是否启用约定式路由 */\n conventional?: boolean;\n /** 约定式路由扫描目录 */\n pagesDir?: string;\n /** 排除的文件/目录模式 */\n exclude?: (string | RegExp)[];\n /**\n * 懒加载的加载状态配置\n * - `false`:禁用全局默认加载状态(各路由仍可通过 loading.tsx 单独配置)\n * - `{ component: string }`:自定义全局默认加载组件的导入路径\n * - 不配置:使用内置默认加载组件\n *\n * @example\n * // 禁用加载状态\n * loading: false\n *\n * @example\n * // 自定义加载组件\n * loading: { component: \"@/components/Loading\" }\n */\n loading?: false | { component: string };\n}\n\n/**\n * 微前端配置\n */\nexport interface MicroFrontendConfig {\n /** 是否启用微前端模式 */\n enabled?: boolean;\n /** 应用名称(用于 UMD 导出) */\n name?: string;\n /** 微前端框架类型 */\n framework?: \"qiankun\" | \"garfish\";\n}\n\n/**\n * 性能配置\n */\nexport interface PerformanceConfig {\n /** 是否启用 Rsdoctor 分析 */\n rsdoctor?: boolean;\n /** 是否开启代码分割 */\n splitChunks?: boolean;\n /** 是否移除 console */\n dropConsole?: boolean;\n}\n\n/**\n * 工具链配置\n */\nexport interface ToolsConfig {\n /**\n * 自定义 Rspack 配置\n * @param config 当前配置\n * @param context 上下文信息\n * @returns 修改后的配置\n */\n rspack?: (\n config: RspackConfig,\n context: { isDev: boolean; isProd: boolean },\n ) => RspackConfig | undefined;\n}\n\n/**\n * 环境变量配置\n */\nexport interface EnvConfig {\n /** 公共环境变量文件路径 */\n publicEnvFile?: string;\n /** 环境特定的变量文件目录 */\n envDir?: string;\n}\n\n/**\n * 框架完整配置\n */\nexport interface YwkfConfig {\n /** 应用名称 */\n appName?: string;\n /** 应用中文名 */\n appCName?: string;\n /** 开发服务器配置 */\n dev?: DevServerConfig;\n /** 输出配置 */\n output?: OutputConfig;\n /** HTML 配置 */\n html?: HtmlConfig;\n /** 样式配置 */\n style?: StyleConfig;\n /** 路由配置 */\n router?: RouterConfig;\n /** 微前端配置 */\n microFrontend?: MicroFrontendConfig;\n /** 性能配置 */\n performance?: PerformanceConfig;\n /** 工具链配置 */\n tools?: ToolsConfig;\n /** 环境变量配置 */\n env?: EnvConfig;\n /** 路径别名 */\n alias?: Record<string, string>;\n /** 插件列表 */\n plugins?: PluginConfig[];\n}\n\n/**\n * 定义配置的辅助函数(提供类型提示)\n */\nexport function defineConfig(config: YwkfConfig): YwkfConfig {\n return config;\n}\n\n/**\n * 默认配置\n */\nexport const defaultConfig: Required<YwkfConfig> = {\n appName: \"app\",\n appCName: \"应用\",\n dev: {\n port: 3000,\n host: \"localhost\",\n proxy: {},\n https: false,\n },\n output: {\n path: \"dist\",\n publicPath: \"/\",\n clean: true,\n },\n html: {\n title: \"应用\",\n template: \"public/index.html\",\n favicon: \"public/favicon.ico\",\n mountRoot: \"root\",\n },\n style: {\n cssModules: true,\n less: { enabled: true, lessOptions: { javascriptEnabled: true } },\n sass: { enabled: true, sassOptions: {} },\n tailwindcss: true,\n },\n router: {\n basename: \"/\",\n conventional: false,\n pagesDir: \"src/pages\",\n exclude: [\n /\\/components?\\//,\n /\\/models\\//,\n /\\/utils?\\//,\n /^_/,\n /\\.d\\.ts$/,\n /\\.(test|spec|e2e)\\.(ts|tsx|js|jsx)$/,\n ],\n },\n microFrontend: {\n enabled: false,\n name: \"app\",\n framework: \"qiankun\",\n },\n performance: {\n rsdoctor: false,\n splitChunks: true,\n dropConsole: false,\n },\n tools: {},\n env: {\n publicEnvFile: \"config/env/.env.public\",\n envDir: \"config/env\",\n },\n alias: {},\n plugins: [],\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/config/loader.ts","../../src/plugin/define.ts","../../src/plugin/builtin/analytics.ts","../../src/plugin/builtin/biome.ts","../../src/plugin/builtin/browser-check.ts","../../src/plugin/builtin/garfish.ts","../../src/plugin/builtin/i18n.ts","../../src/plugin/builtin/mock.ts","../../src/plugin/builtin/react-query.ts","../../src/plugin/builtin/tailwind.ts","../../src/plugin/builtin/theme.ts","../../src/plugin/builtin/zustand.ts","../../src/config/normalize.ts","../../src/config/schema.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { extname, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport deepmerge from \"deepmerge\";\nimport { normalizeConfig } from \"./normalize.js\";\nimport { defaultConfig, type YwkfConfig } from \"./schema.js\";\n\n/** 支持的配置文件名 */\nconst CONFIG_FILES = [\"ywkf.config.ts\", \"ywkf.config.mts\", \"ywkf.config.js\", \"ywkf.config.mjs\"];\n\n/**\n * 查找配置文件\n */\nexport function findConfigFile(cwd: string): string | null {\n for (const file of CONFIG_FILES) {\n const configPath = resolve(cwd, file);\n if (existsSync(configPath)) {\n return configPath;\n }\n }\n return null;\n}\n\n/**\n * 加载 TypeScript 配置文件\n */\nasync function loadTsConfig(configPath: string): Promise<YwkfConfig> {\n const jiti = (await import(\"jiti\")).default;\n const loader = jiti(configPath, {\n interopDefault: true,\n });\n\n const config = loader(configPath);\n return config.default || config;\n}\n\n/**\n * 加载 JavaScript 配置文件\n */\nasync function loadJsConfig(configPath: string): Promise<YwkfConfig> {\n const fileUrl = pathToFileURL(configPath).href;\n const module = await import(fileUrl);\n return module.default || module;\n}\n\n/**\n * 加载配置文件\n */\nexport async function loadConfigFile(configPath: string): Promise<YwkfConfig> {\n const ext = extname(configPath);\n\n if (ext === \".ts\" || ext === \".mts\") {\n return loadTsConfig(configPath);\n }\n\n return loadJsConfig(configPath);\n}\n\n/**\n * 合并配置\n */\nexport function mergeConfig(\n userConfig: YwkfConfig,\n baseConfig: YwkfConfig = defaultConfig,\n): Required<YwkfConfig> {\n return deepmerge(baseConfig, userConfig, {\n arrayMerge: (_, sourceArray) => sourceArray,\n }) as Required<YwkfConfig>;\n}\n\n/**\n * 解析并加载完整配置\n * @param cwd 工作目录\n * @returns 合并后的完整配置\n */\nexport async function resolveConfig(cwd: string): Promise<{\n config: Required<YwkfConfig>;\n configPath: string | null;\n}> {\n const configPath = findConfigFile(cwd);\n\n if (!configPath) {\n console.warn(\"⚠️ 未找到配置文件 (ywkf.config.ts),使用默认配置\");\n return {\n config: defaultConfig as Required<YwkfConfig>,\n configPath: null,\n };\n }\n\n try {\n const userConfig = await loadConfigFile(configPath);\n const normalized = normalizeConfig(userConfig);\n const config = mergeConfig(normalized);\n\n return { config, configPath };\n } catch (error) {\n console.error(\"❌ 配置文件加载失败:\", error);\n throw error;\n }\n}\n\n/**\n * 获取应用路径解析器\n */\nexport function createPathResolver(cwd: string) {\n return {\n resolveApp: (relativePath: string) => resolve(cwd, relativePath),\n cwd,\n };\n}\n","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 { createPlugin } from \"../define.js\";\nimport type { PluginHooks } from \"../types.js\";\n\nexport interface AnalyticsPluginOptions {\n /** 是否启用构建分析 */\n buildAnalysis?: boolean;\n /** 是否输出构建时间 */\n timing?: boolean;\n /** 是否分析 bundle 大小 */\n bundleSize?: boolean;\n /** 大文件警告阈值(KB) */\n sizeWarningThreshold?: number;\n}\n\n/**\n * 构建分析插件\n *\n * @example\n * ```ts\n * import { analyticsPlugin } from \"@4399ywkf/core/plugin\";\n *\n * export default defineConfig({\n * plugins: [\n * analyticsPlugin({\n * timing: true,\n * bundleSize: true,\n * sizeWarningThreshold: 500, // 500KB\n * }),\n * ],\n * });\n * ```\n */\nexport const analyticsPlugin = createPlugin<AnalyticsPluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-analytics\",\n version: \"1.0.0\",\n description: \"构建分析插件\",\n\n setup(context) {\n const {\n buildAnalysis = true,\n timing = true,\n bundleSize = true,\n sizeWarningThreshold = 500,\n } = options;\n const { logger, isProd } = context;\n\n let buildStartTime: number;\n\n const hooks: PluginHooks = {\n beforeBuild() {\n if (timing) {\n buildStartTime = Date.now();\n logger.info(\"开始构建...\");\n }\n },\n\n afterBuild(_context, stats) {\n if (timing) {\n const duration = Date.now() - buildStartTime;\n logger.info(`构建完成,耗时: ${(duration / 1000).toFixed(2)}s`);\n }\n\n if (!stats.success && stats.errors) {\n logger.error(`构建失败,错误数: ${stats.errors.length}`);\n }\n },\n\n modifyRspackConfig(config) {\n if (buildAnalysis && isProd) {\n // 可以在这里添加 bundle analyzer 插件\n logger.info(\"构建分析已启用\");\n }\n\n return config;\n },\n };\n\n return hooks;\n },\n}));\n\nexport default analyticsPlugin;\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createPlugin } from \"../define.js\";\nimport type { PluginHooks } from \"../types.js\";\n\nexport interface BiomePluginOptions {\n /**\n * 是否在项目根目录生成 biome.json(仅在文件不存在时)\n * @default true\n */\n scaffold?: boolean;\n\n /**\n * 额外忽略的文件 glob\n */\n ignore?: string[];\n\n /**\n * 自定义 linter 规则覆盖(浅合并到继承的规则上)\n */\n rules?: Record<string, Record<string, string>>;\n\n /**\n * 自定义 formatter 覆盖\n */\n formatter?: Record<string, unknown>;\n\n /**\n * 自定义 javascript formatter 覆盖\n */\n javascript?: Record<string, unknown>;\n}\n\n/**\n * Biome 代码规范插件\n *\n * 在 setup 阶段自动生成 biome.json,通过 extends 继承\n * @4399ywkf/core 内置的共享配置,为项目提供统一的\n * Lint / Format / Import Sorting 规范。\n *\n * 用户项目的 biome.json 只需 extends 框架配置,\n * 再按需覆盖少量规则即可。\n *\n * @example\n * ```ts\n * import { defineConfig, biomePlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * biomePlugin(),\n * ],\n * });\n * ```\n */\nexport const biomePlugin = createPlugin<BiomePluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-biome\",\n version: \"1.0.0\",\n description: \"Biome 代码规范集成\",\n\n setup(context) {\n const {\n scaffold = true,\n ignore = [],\n rules: customRules,\n formatter: customFormatter,\n javascript: customJavascript,\n } = options;\n\n const { cwd, logger } = context;\n\n if (scaffold) {\n const biomeConfigPath = join(cwd, \"biome.json\");\n if (!existsSync(biomeConfigPath)) {\n const config = buildBiomeConfig({ ignore, customRules, customFormatter, customJavascript });\n writeFileSync(biomeConfigPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n logger.info(\"已生成 biome.json(继承 @4399ywkf/core/biome)\");\n }\n }\n\n const hooks: PluginHooks = {\n modifyRspackConfig(rspackConfig) {\n logger.info(\"Biome 代码规范已启用\");\n return rspackConfig;\n },\n };\n\n return hooks;\n },\n}));\n\ninterface BuildConfigParams {\n ignore: string[];\n customRules?: Record<string, Record<string, string>>;\n customFormatter?: Record<string, unknown>;\n customJavascript?: Record<string, unknown>;\n}\n\nfunction buildBiomeConfig(params: BuildConfigParams) {\n const { ignore, customRules, customFormatter, customJavascript } = params;\n\n const config: Record<string, unknown> = {\n $schema: \"https://biomejs.dev/schemas/2.3.2/schema.json\",\n extends: [\"@4399ywkf/core/biome\"],\n };\n\n if (customFormatter) {\n config.formatter = customFormatter;\n }\n\n if (customJavascript) {\n config.javascript = customJavascript;\n }\n\n if (customRules && Object.keys(customRules).length > 0) {\n config.linter = { rules: customRules };\n }\n\n if (ignore.length > 0) {\n config.files = {\n includes: [\"**\", ...ignore.map((p) => `!${p}`)],\n };\n }\n\n return config;\n}\n\n/**\n * 生成默认 biome.json 配置内容(纯数据,供 CLI 脚手架使用)\n *\n * 生成的配置通过 extends 继承 @4399ywkf/core/biome 共享配置,\n * 用户只需在此基础上按需覆盖。\n */\nexport function getDefaultBiomeConfig(): Record<string, unknown> {\n return buildBiomeConfig({ ignore: [] });\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createPlugin } from \"../define.js\";\nimport type { PluginHooks } from \"../types.js\";\n\n/**\n * 浏览器版本要求\n */\nexport interface BrowserMinVersions {\n chrome?: number;\n edge?: number;\n firefox?: number;\n safari?: number;\n}\n\nexport interface BrowserCheckPluginOptions {\n /**\n * 需要检测的浏览器特性(API 级别的特性检测)\n * @default [\"Object.hasOwn\"]\n * @example [\"Object.hasOwn\", \"Array.prototype.at\", \"structuredClone\"]\n */\n features?: string[];\n\n /**\n * 最低浏览器版本要求(基于 UA 解析)\n *\n * 优先级:`minVersions` > `fromBrowserslist` 解析结果 > 内置默认值\n *\n * @default { chrome: 93, edge: 93, firefox: 92, safari: 15.4 }\n */\n minVersions?: BrowserMinVersions;\n\n /**\n * 从 `.browserslistrc` 文件或 `package.json` 的 `browserslist` 字段中\n * 自动读取最低浏览器版本要求。\n *\n * - `true` — 自动在项目根目录查找 `.browserslistrc` 或 `package.json#browserslist`\n * - `string` — 指定 `.browserslistrc` 文件的路径(相对于项目根目录)\n * - `false` — 不读取,使用 `minVersions` 或内置默认值\n *\n * 如果同时配置了 `minVersions`,`minVersions` 中的值会**覆盖** `.browserslistrc` 中的对应值。\n *\n * @default false\n *\n * @example\n * ```ts\n * // 自动检测\n * browserCheckPlugin({ fromBrowserslist: true })\n *\n * // 指定路径\n * browserCheckPlugin({ fromBrowserslist: \"../.browserslistrc\" })\n *\n * // 自动读取 + 覆盖 safari 版本\n * browserCheckPlugin({ fromBrowserslist: true, minVersions: { safari: 16 } })\n * ```\n */\n fromBrowserslist?: boolean | string;\n\n /**\n * 警告页面标题\n * @default \"浏览器版本过低\"\n */\n title?: string;\n\n /**\n * 警告页面描述信息\n * @default \"您当前的浏览器版本不支持本应用所需的功能。请升级到以下推荐浏览器的最新版本:\"\n */\n message?: string;\n\n /**\n * 是否显示推荐浏览器下载链接\n * @default true\n */\n showDownloadLinks?: boolean;\n\n /**\n * 自定义渲染 HTML 的函数。如果提供,将替代默认的警告页面。\n */\n renderHtml?: (opts: {\n title: string;\n message: string;\n showDownloadLinks: boolean;\n minVersions: BrowserMinVersions;\n }) => string;\n\n /**\n * 伴随自定义 HTML 执行的 JS 脚本代码(字符串形式)。\n * 注意:这段代码会在不支持的浏览器中执行,请使用 ES5 语法。\n */\n renderScript?: string;\n}\n\nconst DEFAULT_FEATURES = [\"Object.hasOwn\"];\n\nconst DEFAULT_MIN_VERSIONS: BrowserMinVersions = {\n chrome: 93,\n edge: 93,\n firefox: 92,\n safari: 15.4,\n};\n\n/**\n * 浏览器最低版本检查插件\n *\n * 在应用启动前检测浏览器兼容性,若不满足要求则展示升级提示页面,阻止应用加载。\n * 支持两种检测策略:\n * 1. **特性检测**(推荐):检查浏览器是否支持指定的 API,如 `Object.hasOwn`\n * 2. **UA 版本检测**:解析 User-Agent 判断浏览器版本是否达到最低要求\n *\n * @see https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn\n *\n * @example\n * ```ts\n * import { defineConfig, browserCheckPlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * browserCheckPlugin(),\n * ],\n * });\n * ```\n *\n * @example\n * ```ts\n * // 自定义最低版本和检测特性\n * browserCheckPlugin({\n * features: [\"Object.hasOwn\", \"Array.prototype.at\"],\n * minVersions: { chrome: 100, edge: 100, firefox: 100, safari: 16 },\n * title: \"请升级浏览器\",\n * message: \"当前浏览器版本过低,无法正常使用本系统。\",\n * })\n * ```\n *\n * @example\n * ```ts\n * // 从 .browserslistrc 自动读取最低版本要求\n * browserCheckPlugin({\n * fromBrowserslist: true,\n * })\n * ```\n *\n * @example\n * ```ts\n * // 从 .browserslistrc 读取,并覆盖 safari 版本\n * browserCheckPlugin({\n * fromBrowserslist: true,\n * minVersions: { safari: 16 },\n * })\n * ```\n */\nexport const browserCheckPlugin = createPlugin<BrowserCheckPluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-browser-check\",\n version: \"1.0.0\",\n description: \"浏览器最低版本检查插件\",\n\n setup(context) {\n const {\n features = DEFAULT_FEATURES,\n minVersions: explicitVersions,\n fromBrowserslist = false,\n title = \"浏览器版本过低\",\n message = \"您当前的浏览器版本不支持本应用所需的功能。请升级到以下推荐浏览器的最新版本:\",\n showDownloadLinks = true,\n renderHtml,\n renderScript,\n } = options;\n\n const { cwd, config, logger } = context;\n const rootId = config.html.mountRoot || config.appName || \"root\";\n\n // 解析最终的 minVersions:browserslistrc → 默认值 → 用户显式覆盖\n let baseVersions = { ...DEFAULT_MIN_VERSIONS };\n\n if (fromBrowserslist !== false) {\n const parsed = parseBrowserslistConfig(cwd, fromBrowserslist, logger);\n if (parsed) {\n baseVersions = { ...baseVersions, ...parsed };\n }\n }\n\n const minVersions: BrowserMinVersions = explicitVersions\n ? { ...baseVersions, ...explicitVersions }\n : baseVersions;\n\n logger.info(\n `浏览器兼容性检查已启用 (特性检测: ${features.join(\", \")})`,\n );\n logger.info(\n `最低版本要求: Chrome ${minVersions.chrome ?? \"—\"}, Edge ${minVersions.edge ?? \"—\"}, Firefox ${minVersions.firefox ?? \"—\"}, Safari ${minVersions.safari ?? \"—\"}${fromBrowserslist !== false ? \" (从 browserslist 读取)\" : \"\"}`,\n );\n\n const hooks: PluginHooks = {\n modifyEntryCode(code) {\n const featureCheckLines = buildFeatureChecks(features);\n const versionCheckLines = buildVersionChecks(minVersions);\n \n const warningHtml = renderHtml \n ? renderHtml({ title, message, showDownloadLinks, minVersions })\n : buildWarningHtml({ title, message, showDownloadLinks, minVersions });\n\n const checkBlock = [\n ``,\n `// ======= 浏览器兼容性检查 (@4399ywkf/plugin-browser-check) =======`,\n `const __ywkfBrowserOk = (() => {`,\n ` try {`,\n ...featureCheckLines.map((l) => ` ${l}`),\n ...versionCheckLines.map((l) => ` ${l}`),\n ` return true;`,\n ` } catch {`,\n ` return false;`,\n ` }`,\n `})();`,\n ``,\n `if (!__ywkfBrowserOk) {`,\n ` const __root = document.getElementById(${JSON.stringify(rootId)}) || document.body;`,\n ` __root.innerHTML = ${JSON.stringify(warningHtml)};`,\n renderScript ? ` ${renderScript}` : ``,\n `}`,\n `// ======= End 浏览器兼容性检查 =======`,\n ``,\n ].join(\"\\n\");\n\n // 在最后一条 import 语句之后插入检查代码\n const lines = code.split(\"\\n\");\n let lastImportIndex = -1;\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].trimStart().startsWith(\"import \")) {\n lastImportIndex = i;\n }\n }\n const insertIndex = lastImportIndex >= 0 ? lastImportIndex + 1 : 0;\n lines.splice(insertIndex, 0, checkBlock);\n\n // 将 runApp() 替换为条件调用,确保浏览器不兼容时不启动应用\n let result = lines.join(\"\\n\");\n result = result.replace(\n /(\\s*)(await\\s+)?runApp\\(\\);?/g,\n (_, indent: string, awaitKw?: string) =>\n `${indent}if (__ywkfBrowserOk) { ${awaitKw || \"\"}runApp(); }`,\n );\n\n return result;\n },\n };\n\n return hooks;\n },\n}));\n\n// ---------------------------------------------------------------------------\n// 内部辅助函数\n// ---------------------------------------------------------------------------\n\n/**\n * 生成特性检测代码行\n */\nfunction buildFeatureChecks(features: string[]): string[] {\n if (features.length === 0) return [];\n\n const lines: string[] = [\"// 特性检测\"];\n for (const feature of features) {\n const parts = feature.split(\".\");\n if (parts.length === 1) {\n lines.push(`if (typeof ${feature} === \"undefined\") return false;`);\n } else {\n lines.push(`if (typeof ${feature} !== \"function\") return false;`);\n }\n }\n return lines;\n}\n\n/**\n * 生成 UA 版本检测代码行\n */\nfunction buildVersionChecks(minVersions: BrowserMinVersions): string[] {\n const entries = Object.entries(minVersions).filter(\n ([, v]) => v != null,\n ) as [string, number][];\n if (entries.length === 0) return [];\n\n const lines: string[] = [\"// UA 版本检测\", \"const ua = navigator.userAgent;\"];\n\n for (const [browser, minVer] of entries) {\n switch (browser) {\n case \"chrome\":\n lines.push(\n `const chromeMatch = /Chrome\\\\/(\\\\d+)/.exec(ua);`,\n `if (chromeMatch && !/Edg\\\\//.test(ua) && Number(chromeMatch[1]) < ${minVer}) return false;`,\n );\n break;\n case \"edge\":\n lines.push(\n `const edgeMatch = /Edg\\\\/(\\\\d+)/.exec(ua);`,\n `if (edgeMatch && Number(edgeMatch[1]) < ${minVer}) return false;`,\n );\n break;\n case \"firefox\":\n lines.push(\n `const firefoxMatch = /Firefox\\\\/(\\\\d+)/.exec(ua);`,\n `if (firefoxMatch && Number(firefoxMatch[1]) < ${minVer}) return false;`,\n );\n break;\n case \"safari\":\n lines.push(\n `const safariMatch = /Version\\\\/(\\\\d+\\\\.?\\\\d*)/.exec(ua);`,\n `if (safariMatch && /Safari/.test(ua) && !/Chrome/.test(ua) && Number(safariMatch[1]) < ${minVer}) return false;`,\n );\n break;\n }\n }\n\n return lines;\n}\n\n/**\n * 生成浏览器升级提示的 HTML\n */\nfunction buildWarningHtml(opts: {\n title: string;\n message: string;\n showDownloadLinks: boolean;\n minVersions: BrowserMinVersions;\n}): string {\n const { title, message, showDownloadLinks, minVersions } = opts;\n\n const versionHints = [\n minVersions.chrome != null && `Chrome ${minVersions.chrome}+`,\n minVersions.edge != null && `Edge ${minVersions.edge}+`,\n minVersions.firefox != null && `Firefox ${minVersions.firefox}+`,\n minVersions.safari != null && `Safari ${minVersions.safari}+`,\n ]\n .filter(Boolean)\n .join(\"、\");\n\n const downloadLinksHtml = showDownloadLinks\n ? `<div style=\"display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:32px\">${browserLink(\"https://www.google.cn/chrome/\", \"Chrome 浏览器\", \"#4285f4\", \"#356ac3\", \"66,133,244\")}${browserLink(\"https://www.microsoft.com/edge\", \"Edge 浏览器\", \"#0078d4\", \"#005a9e\", \"0,120,212\")}${browserLink(\"https://www.firefox.com.cn/\", \"Firefox 浏览器\", \"#ff7139\", \"#e05a2b\", \"255,113,57\")}</div>`\n : \"\";\n\n const versionHintHtml = versionHints\n ? `<p style=\"margin:28px 0 0;font-size:13px;color:#aaa;letter-spacing:0.3px\">推荐版本:${versionHints}</p>`\n : \"\";\n\n /* eslint-disable max-len */\n return [\n `<div style=\"position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#f5f7fa 0%,#c3cfe2 100%);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'PingFang SC','Microsoft YaHei',sans-serif;padding:24px;box-sizing:border-box\">`,\n `<div style=\"max-width:520px;width:100%;padding:48px 40px;background:#fff;border-radius:20px;box-shadow:0 8px 40px rgba(0,0,0,0.12);text-align:center\">`,\n // 警告图标\n `<div style=\"width:80px;height:80px;margin:0 auto 28px;background:linear-gradient(135deg,#ff9a56,#ff6b6b);border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 20px rgba(255,107,107,0.3)\">`,\n `<svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z\"/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/></svg>`,\n `</div>`,\n // 标题 & 描述\n `<h1 style=\"margin:0 0 16px;font-size:26px;font-weight:700;color:#1a1a2e;letter-spacing:-0.5px\">${title}</h1>`,\n `<p style=\"margin:0;font-size:15px;color:#666;line-height:1.8\">${message}</p>`,\n // 下载链接\n downloadLinksHtml,\n // 版本提示\n versionHintHtml,\n `</div></div>`,\n ].join(\"\");\n /* eslint-enable max-len */\n}\n\n/**\n * 生成单个浏览器下载链接 HTML\n */\nfunction browserLink(\n href: string,\n label: string,\n colorStart: string,\n colorEnd: string,\n rgbBase: string,\n): string {\n const bg = `background:linear-gradient(135deg,${colorStart},${colorEnd})`;\n const shadow = `box-shadow:0 4px 12px rgba(${rgbBase},0.3)`;\n const hoverShadow = `0 6px 20px rgba(${rgbBase},0.4)`;\n const base = `display:inline-flex;align-items:center;padding:14px 28px;${bg};color:#fff;border-radius:12px;text-decoration:none;font-size:15px;font-weight:500;${shadow};transition:transform .2s,box-shadow .2s`;\n\n return `<a href=\"${href}\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"${base}\" onmouseover=\"this.style.transform='translateY(-2px)';this.style.boxShadow='${hoverShadow}'\" onmouseout=\"this.style.transform='';this.style.boxShadow='0 4px 12px rgba(${rgbBase},0.3)'\">${label}</a>`;\n}\n\n// ---------------------------------------------------------------------------\n// .browserslistrc 解析\n// ---------------------------------------------------------------------------\n\n/**\n * browserslistrc 中的浏览器名称 → 插件 BrowserMinVersions key 的映射\n */\nconst BROWSERSLIST_NAME_MAP: Record<string, keyof BrowserMinVersions> = {\n chrome: \"chrome\",\n chromium: \"chrome\",\n edge: \"edge\",\n firefox: \"firefox\",\n ff: \"firefox\",\n safari: \"safari\",\n ios_saf: \"safari\",\n};\n\n/**\n * 从项目中解析 browserslist 配置,提取最低浏览器版本\n *\n * 支持以下格式:\n * - `.browserslistrc` 文件(每行一条查询)\n * - `package.json` 中的 `browserslist` 字段(数组或字符串)\n *\n * 仅识别简单的版本查询格式:\n * - `chrome >= 51`\n * - `firefox > 53`(会自动 +1 转换为 >= 54)\n * - `safari 10`(精确版本视为 >=)\n */\nfunction parseBrowserslistConfig(\n cwd: string,\n source: true | string,\n logger: { info: (msg: string) => void; warn: (msg: string) => void },\n): BrowserMinVersions | null {\n let queries: string[] = [];\n\n if (typeof source === \"string\") {\n // 用户指定路径\n const filePath = join(cwd, source);\n if (!existsSync(filePath)) {\n logger.warn(`browserslist 文件未找到: ${filePath}`);\n return null;\n }\n queries = readBrowserslistFile(filePath);\n logger.info(`从 ${source} 读取到 ${queries.length} 条 browserslist 查询`);\n } else {\n // 自动检测:先找 .browserslistrc,再找 package.json\n const rcPath = join(cwd, \".browserslistrc\");\n if (existsSync(rcPath)) {\n queries = readBrowserslistFile(rcPath);\n logger.info(`从 .browserslistrc 读取到 ${queries.length} 条 browserslist 查询`);\n } else {\n const pkgPath = join(cwd, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n if (Array.isArray(pkg.browserslist)) {\n queries = pkg.browserslist;\n logger.info(`从 package.json#browserslist 读取到 ${queries.length} 条查询`);\n } else if (typeof pkg.browserslist === \"string\") {\n queries = [pkg.browserslist];\n logger.info(\"从 package.json#browserslist 读取到 1 条查询\");\n }\n } catch {\n // ignore JSON parse error\n }\n }\n }\n\n if (queries.length === 0) {\n logger.warn(\"未找到 .browserslistrc 或 package.json#browserslist,将使用内置默认值\");\n return null;\n }\n }\n\n return extractMinVersions(queries);\n}\n\nfunction readBrowserslistFile(filePath: string): string[] {\n const content = readFileSync(filePath, \"utf-8\");\n return content\n .split(\"\\n\")\n .map((line) => line.replace(/#.*$/, \"\").trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"));\n}\n\n/**\n * 从 browserslist 查询数组中提取各浏览器的最低版本\n *\n * 支持格式:\n * - `chrome >= 51`\n * - `chrome > 50` → chrome >= 51\n * - `chrome 51` → chrome >= 51\n * - `chrome >= 51, firefox >= 54`(逗号分隔)\n */\nfunction extractMinVersions(queries: string[]): BrowserMinVersions {\n const result: BrowserMinVersions = {};\n\n // 展开逗号分隔的多条查询\n const expanded = queries.flatMap((q) => q.split(\",\").map((s) => s.trim()));\n\n const versionPattern = /^(\\w+)\\s*(?:(>=?)\\s*)?(\\d+(?:\\.\\d+)?)\\s*$/i;\n\n for (const query of expanded) {\n // 跳过 \"not\" / \"dead\" / \"last N versions\" 等复杂查询\n if (/^(not|dead|last|defaults|>?\\s*\\d+%|unreleased|current)/i.test(query)) {\n continue;\n }\n\n const match = versionPattern.exec(query);\n if (!match) continue;\n\n const [, browserName, operator, versionStr] = match;\n const key = BROWSERSLIST_NAME_MAP[browserName.toLowerCase()];\n if (!key) continue;\n\n let version = Number.parseFloat(versionStr);\n if (operator === \">\") {\n version = Math.ceil(version) + 1;\n }\n\n // 取最低值(如果同一浏览器出现多次)\n if (result[key] == null || version < result[key]!) {\n result[key] = version;\n }\n }\n\n return result;\n}\n\nexport default browserCheckPlugin;\n","import { createPlugin } from \"../define.js\";\nimport type { CodeInjection, GeneratorContext, PluginHooks } from \"../types.js\";\n\nexport interface GarfishPluginOptions {\n /** 应用名称(微前端标识) */\n appName?: string;\n /** 是否作为主应用 */\n master?: boolean;\n /** 子应用列表(主应用模式) */\n apps?: {\n name: string;\n entry: string;\n activeRule: string;\n basename?: string;\n }[];\n /** 沙箱配置 */\n sandbox?: {\n /** 是否开启 JS 沙箱 */\n open?: boolean;\n /** 是否开启快照沙箱 */\n snapshot?: boolean;\n /** 样式隔离 */\n strictStyleIsolation?: boolean;\n };\n}\n\n/**\n * Garfish 微前端插件\n *\n * 通过插件方式启用微前端功能,支持子应用和主应用两种模式。\n *\n * @example\n * ```ts\n * // ywkf.config.ts - 子应用模式\n * import { defineConfig, garfishPlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * garfishPlugin({\n * appName: \"sub-app\",\n * }),\n * ],\n * });\n * ```\n *\n * @example\n * ```ts\n * // ywkf.config.ts - 主应用模式\n * import { defineConfig, garfishPlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * garfishPlugin({\n * master: true,\n * apps: [\n * { name: \"sub-app\", entry: \"http://localhost:3001\", activeRule: \"/sub\" },\n * ],\n * }),\n * ],\n * });\n * ```\n */\nexport const garfishPlugin = createPlugin<GarfishPluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-garfish\",\n version: \"1.0.0\",\n description: \"Garfish 微前端插件\",\n\n setup(context) {\n const { appName, master = false, apps = [], sandbox = {} } = options;\n const { config, logger, isDev } = context;\n const finalAppName = appName || config.appName;\n\n const hooks: PluginHooks = {\n // ===== 构建阶段钩子 =====\n modifyRspackConfig(rspackConfig) {\n // 微前端子应用需要 UMD 输出 + CORS\n if (!master) {\n rspackConfig.output = {\n ...rspackConfig.output,\n library: finalAppName,\n libraryTarget: \"umd\",\n globalObject: \"window\",\n chunkLoadingGlobal: `garfish_${finalAppName}`,\n };\n\n // 子应用 dev server 必须允许跨域(主应用需要跨域加载子应用资源)\n rspackConfig.devServer = {\n ...rspackConfig.devServer,\n headers: {\n ...(((rspackConfig.devServer as Record<string, unknown>)?.headers as Record<\n string,\n string\n >) || {}),\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"*\",\n },\n };\n\n logger.info(`配置 UMD 输出: ${finalAppName}`);\n }\n\n return rspackConfig;\n },\n\n beforeDevServer() {\n if (master) {\n logger.info(\"Garfish 主应用模式\");\n logger.info(`子应用列表: ${apps.map((a) => a.name).join(\", \")}`);\n } else {\n logger.info(`Garfish 子应用模式: ${finalAppName}`);\n }\n },\n\n // ===== 代码生成阶段钩子 =====\n injectEntry(_ctx: GeneratorContext): CodeInjection {\n if (master && apps.length > 0) {\n return {\n imports: [`import { initGarfishMaster } from \"./bootstrap\";`],\n topLevel: [`// Garfish 主应用:初始化微前端并注册子应用`, `await initGarfishMaster();`],\n };\n }\n\n if (!master) {\n return {\n imports: [`import { garfishProvider, isMicroAppEnv } from \"./bootstrap\";`],\n exports: [\n `// Garfish 子应用生命周期导出(provider 函数格式)`,\n `export const provider = garfishProvider;`,\n ],\n topLevel: [\n `// Garfish 微前端:独立运行判断`,\n `const shouldRunIndependently = !isMicroAppEnv();`,\n ],\n };\n }\n\n return {};\n },\n\n injectBootstrap(_ctx: GeneratorContext): CodeInjection {\n const imports: string[] = [];\n const exports: string[] = [];\n const topLevel: string[] = [];\n\n if (master) {\n // 主应用模式\n if (apps.length > 0) {\n imports.push(`import Garfish from \"garfish\";`);\n topLevel.push(generateMasterInitCode(apps, config.router.basename));\n }\n } else {\n // 子应用模式:使用 Garfish 专用 provider 格式\n imports.push(\n `import { createGarfishProvider, isMicroAppEnv } from \"@4399ywkf/core/runtime\";`,\n );\n exports.push(\n `/**`,\n ` * Garfish 子应用 provider(render/destroy 格式)`,\n ` */`,\n `export const garfishProvider = createGarfishProvider(createAppConfig);`,\n ``,\n `/**`,\n ` * 判断是否在微前端环境`,\n ` */`,\n `export { isMicroAppEnv };`,\n );\n }\n\n return { imports, exports, topLevel };\n },\n\n modifyBootstrapCode(code: string, _ctx: GeneratorContext): string {\n // 微前端子应用禁用 antd 配置(由主应用管理)\n if (!master) {\n return code.replace(/antd:\\s*\\{\\s*enabled:\\s*true/, \"antd: { enabled: false\");\n }\n return code;\n },\n\n // ===== 运行时阶段钩子 =====\n modifyAppConfig(appConfig) {\n return {\n ...appConfig,\n // 微前端模式下禁用 antd 样式注入(由主应用管理)\n antd: {\n ...appConfig.antd,\n enabled: master,\n },\n };\n },\n };\n\n return hooks;\n },\n}));\n\n/**\n * 生成主应用初始化代码\n */\nfunction generateMasterInitCode(\n apps: NonNullable<GarfishPluginOptions[\"apps\"]>,\n basename?: string,\n): string {\n const appConfigs = apps\n .map(\n (app) => `{\n name: \"${app.name}\",\n entry: \"${app.entry}\",\n activeWhen: \"${app.activeRule}\",\n ${app.basename ? `basename: \"${app.basename}\",` : \"\"}\n }`,\n )\n .join(\",\\n \");\n\n return `\n/**\n * Garfish 主应用初始化\n * 在 runApp 之前调用\n */\nexport async function initGarfishMaster(): Promise<void> {\n await Garfish.run({\n basename: \"${basename || \"/\"}\",\n domGetter: \"#subapp-container\",\n apps: [\n ${appConfigs}\n ],\n });\n}\n`;\n}\n\nexport default garfishPlugin;\n","import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createPlugin } from \"../define.js\";\nimport type { CodeInjection, GeneratedFile, GeneratorContext, PluginHooks } from \"../types.js\";\n\nexport interface I18nPluginOptions {\n /**\n * 默认语言\n * @default \"zh-CN\"\n */\n defaultLocale?: string;\n\n /**\n * 支持的语言列表\n * @default [\"zh-CN\", \"en-US\"]\n */\n locales?: string[];\n\n /**\n * 翻译 JSON 文件目录(相对于项目根目录)\n * 非默认语言的 JSON 翻译文件存放位置\n * @default \"locales\"\n */\n localesDir?: string;\n\n /**\n * 默认语言 TS 源文件目录(相对于项目根目录)\n * 开发者在此编写 TypeScript 翻译源文件,作为 i18n 的 single source of truth\n * @default \"src/locales/default\"\n */\n sourceDir?: string;\n\n /**\n * 默认命名空间\n * @default [\"common\"]\n */\n defaultNS?: string[];\n\n /**\n * 是否自动生成初始脚手架文件\n * @default true\n */\n autoScaffold?: boolean;\n}\n\n/**\n * 国际化插件(TS-first 工作流)\n *\n * 开发流程:\n * 1. 开发者在 src/locales/default/ 中编写 TypeScript 翻译源文件(有类型推导 + IDE 补全)\n * 2. 运行 `pnpm i18n:gen` 将 TS 源文件转换为 locales/{defaultLocale}/*.json\n * 3. 运行 `pnpm i18n` 使用 @lobehub/i18n-cli 将默认语言 JSON 翻译为其他语言\n * 4. 运行时:开发模式下默认语言直接 import TS,其他场景懒加载 JSON\n *\n * @example\n * ```ts\n * import { defineConfig, i18nPlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * i18nPlugin({\n * defaultLocale: \"zh-CN\",\n * locales: [\"zh-CN\", \"en-US\", \"ja-JP\"],\n * }),\n * ],\n * });\n * ```\n */\nexport const i18nPlugin = createPlugin<I18nPluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-i18n\",\n version: \"1.0.0\",\n description: \"国际化 (i18next) 插件 — TS-first 工作流\",\n\n setup(context) {\n const {\n defaultLocale = \"zh-CN\",\n locales = [\"zh-CN\", \"en-US\"],\n localesDir = \"locales\",\n sourceDir = \"src/locales/default\",\n defaultNS = [\"common\"],\n autoScaffold = true,\n } = options;\n const { cwd, logger, isDev } = context;\n\n if (autoScaffold) {\n scaffoldSourceFiles(cwd, sourceDir, defaultNS, logger);\n scaffoldResourcesFile(cwd, sourceDir, defaultNS, locales, defaultLocale, logger);\n scaffoldConvertScript(cwd, sourceDir, localesDir, defaultLocale, logger);\n scaffoldI18nRc(cwd, localesDir, defaultLocale, locales, logger);\n scaffoldLocaleJsonDirs(cwd, localesDir, locales, defaultLocale, defaultNS, logger);\n }\n\n const hooks: PluginHooks = {\n modifyRspackConfig(rspackConfig) {\n const aliases = (rspackConfig.resolve?.alias || {}) as Record<string, string>;\n if (!aliases[\"@locales\"]) {\n aliases[\"@locales\"] = join(cwd, localesDir);\n }\n rspackConfig.resolve = { ...rspackConfig.resolve, alias: aliases };\n return rspackConfig;\n },\n\n generateFiles(_ctx: GeneratorContext): GeneratedFile[] {\n return [\n {\n path: \"i18n.ts\",\n content: generateI18nCode({\n defaultLocale,\n locales,\n localesDir,\n sourceDir,\n defaultNS,\n isDev,\n }),\n },\n ];\n },\n\n injectBootstrap(_ctx: GeneratorContext): CodeInjection {\n return {\n imports: [`import { initI18n } from \"./i18n\";`],\n topLevel: [`await initI18n();`],\n };\n },\n };\n\n return hooks;\n },\n}));\n\n// ============ 代码生成 ============\n\nfunction generateI18nCode(opts: {\n defaultLocale: string;\n locales: string[];\n localesDir: string;\n sourceDir: string;\n defaultNS: string[];\n isDev: boolean;\n}): string {\n const { defaultLocale, locales, defaultNS, sourceDir } = opts;\n\n // sourceDir = \"src/locales/default\"\n // → defaultDirAlias = \"locales/default\" (相对于 @/ 的路径)\n // → parentDirAlias = \"locales\" (resources.ts 所在目录)\n const defaultDirAlias = sourceDir.replace(/^src\\//, \"\");\n const parentDirAlias = defaultDirAlias.replace(/\\/[^/]+$/, \"\");\n\n return `// 此文件由 @4399ywkf/plugin-i18n 自动生成\nimport i18n from \"i18next\";\nimport LanguageDetector from \"i18next-browser-languagedetector\";\nimport resourcesToBackend from \"i18next-resources-to-backend\";\nimport { initReactI18next } from \"react-i18next\";\nimport { normalizeLocale, SUPPORTED_LOCALES, DEFAULT_LOCALE } from \"@/${parentDirAlias}/resources\";\n\nexport { DEFAULT_LOCALE, SUPPORTED_LOCALES, normalizeLocale };\nexport type { SupportedLocale, NS } from \"@/${parentDirAlias}/resources\";\n\nconst isDev = process.env.NODE_ENV === \"development\";\n\nconst instance = i18n\n .use(initReactI18next)\n .use(LanguageDetector)\n .use(\n resourcesToBackend(async (lng: string, ns: string) => {\n const normalizedLng = normalizeLocale(lng);\n\n // 开发模式下,默认语言直接 import TS(即时生效,无需先生成 JSON)\n if (isDev && normalizedLng === \"${defaultLocale}\") {\n return import(\"@/${defaultDirAlias}/\" + ns);\n }\n\n // 其他语言 / 生产模式:懒加载 JSON\n return import(\n /* webpackInclude: /\\\\.json$/ */\n /* webpackChunkName: \"locales-[request]\" */\n \\`@locales/\\${normalizedLng}/\\${ns}.json\\`\n );\n })\n );\n\nlet initialized = false;\n\nexport async function initI18n(lang?: string): Promise<typeof i18n> {\n if (initialized) return instance;\n\n await instance.init({\n defaultNS: ${JSON.stringify(defaultNS)},\n fallbackLng: DEFAULT_LOCALE,\n interpolation: { escapeValue: false },\n lng: lang,\n });\n\n initialized = true;\n return instance;\n}\n\nexport { instance as i18n };\nexport default instance;\n`;\n}\n\n// ============ 脚手架:TS 源文件 ============\n\nfunction scaffoldSourceFiles(\n cwd: string,\n sourceDir: string,\n namespaces: string[],\n logger: { info: (msg: string) => void },\n): void {\n const dir = join(cwd, sourceDir);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n for (const ns of namespaces) {\n const filePath = join(dir, `${ns}.ts`);\n if (!existsSync(filePath)) {\n writeFileSync(filePath, buildDefaultNsFile(ns), \"utf-8\");\n logger.info(`已生成翻译源文件: ${sourceDir}/${ns}.ts`);\n }\n }\n\n // 生成 index.ts barrel\n const indexPath = join(dir, \"index.ts\");\n if (!existsSync(indexPath)) {\n const imports = namespaces.map((ns) => `import ${ns} from \"./${ns}\";`).join(\"\\n\");\n const entries = namespaces.join(\",\\n \");\n const content = `${imports}\n\nconst resources = {\n ${entries},\n} as const;\n\nexport default resources;\n`;\n writeFileSync(indexPath, content, \"utf-8\");\n logger.info(`已生成翻译索引: ${sourceDir}/index.ts`);\n }\n}\n\nfunction buildDefaultNsFile(ns: string): string {\n if (ns === \"common\") {\n return `export default {\n welcome: \"欢迎使用\",\n loading: \"加载中...\",\n confirm: \"确定\",\n cancel: \"取消\",\n save: \"保存\",\n delete: \"删除\",\n edit: \"编辑\",\n back: \"返回\",\n} as const;\n`;\n }\n\n return `export default {\n title: \"${ns}\",\n} as const;\n`;\n}\n\n// ============ 脚手架:resources.ts 类型文件 ============\n\nfunction scaffoldResourcesFile(\n cwd: string,\n sourceDir: string,\n _namespaces: string[],\n locales: string[],\n defaultLocale: string,\n logger: { info: (msg: string) => void },\n): void {\n const parentDir = join(cwd, sourceDir, \"..\");\n const filePath = join(parentDir, \"resources.ts\");\n if (existsSync(filePath)) return;\n\n const content = `import resources from \"./default\";\n\nexport const DEFAULT_LOCALE = \"${defaultLocale}\";\n\nexport const SUPPORTED_LOCALES = ${JSON.stringify(locales)} as const;\n\nexport type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];\n\nexport type DefaultResources = typeof resources;\n\nexport type NS = keyof DefaultResources;\n\nexport const normalizeLocale = (locale?: string): SupportedLocale => {\n if (!locale) return DEFAULT_LOCALE as SupportedLocale;\n\n for (const l of SUPPORTED_LOCALES) {\n if (l.startsWith(locale) || locale.startsWith(l.split(\"-\")[0])) {\n return l;\n }\n }\n\n return DEFAULT_LOCALE as SupportedLocale;\n};\n\nexport const localeOptions = ${JSON.stringify(\n locales.map((l) => ({ value: l, label: getLocaleLabel(l) })),\n null,\n 2,\n )} as const;\n`;\n\n writeFileSync(filePath, content, \"utf-8\");\n logger.info(`已生成类型文件: ${sourceDir}/../resources.ts`);\n}\n\nfunction getLocaleLabel(locale: string): string {\n const map: Record<string, string> = {\n \"zh-CN\": \"简体中文\",\n \"zh-TW\": \"繁體中文\",\n \"en-US\": \"English\",\n \"ja-JP\": \"日本語\",\n \"ko-KR\": \"한국어\",\n \"de-DE\": \"Deutsch\",\n \"fr-FR\": \"Français\",\n \"es-ES\": \"Español\",\n \"pt-BR\": \"Português\",\n \"ru-RU\": \"Русский\",\n \"it-IT\": \"Italiano\",\n \"vi-VN\": \"Tiếng Việt\",\n ar: \"العربية\",\n };\n return map[locale] || locale;\n}\n\n// ============ 脚手架:转换脚本 ============\n\nfunction scaffoldConvertScript(\n cwd: string,\n sourceDir: string,\n localesDir: string,\n defaultLocale: string,\n logger: { info: (msg: string) => void },\n): void {\n const scriptsDir = join(cwd, \"scripts\");\n const scriptPath = join(scriptsDir, \"i18n-gen.js\");\n if (existsSync(scriptPath)) return;\n\n if (!existsSync(scriptsDir)) {\n mkdirSync(scriptsDir, { recursive: true });\n }\n\n const content = `const fs = require(\"fs\");\nconst path = require(\"path\");\n\nconst sourceDir = path.join(__dirname, \"../${sourceDir}\");\nconst targetDir = path.join(__dirname, \"../${localesDir}/${defaultLocale}\");\n\nconst files = fs\n .readdirSync(sourceDir)\n .filter((file) => file.endsWith(\".ts\") && file !== \"index.ts\")\n .map((file) => path.basename(file, \".ts\"));\n\nrequire(\"ts-node/register\");\n\nif (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n}\n\nconsole.log(\"开始转换 TypeScript 文件到 JSON...\\\\n\");\n\nfiles.forEach((fileName) => {\n try {\n const modulePath = path.join(sourceDir, \\`\\${fileName}.ts\\`);\n delete require.cache[require.resolve(modulePath)];\n const moduleContent = require(modulePath).default;\n const jsonContent = JSON.stringify(moduleContent, null, 2);\n const targetPath = path.join(targetDir, \\`\\${fileName}.json\\`);\n fs.writeFileSync(targetPath, jsonContent, \"utf8\");\n console.log(\\` \\${fileName}.ts → \\${fileName}.json\\`);\n } catch (error) {\n console.error(\\` 转换 \\${fileName}.ts 失败:\\`, error.message);\n }\n});\n\nconsole.log(\"\\\\n转换完成!\");\n`;\n\n writeFileSync(scriptPath, content, \"utf-8\");\n logger.info(\"已生成转换脚本: scripts/i18n-gen.js\");\n}\n\n// ============ 脚手架:.i18nrc.js(@lobehub/i18n-cli 配置) ============\n\nfunction scaffoldI18nRc(\n cwd: string,\n localesDir: string,\n defaultLocale: string,\n locales: string[],\n logger: { info: (msg: string) => void },\n): void {\n const filePath = join(cwd, \".i18nrc.js\");\n if (existsSync(filePath)) return;\n\n const outputLocales = locales\n .filter((l) => l !== defaultLocale)\n .map((l) => `\"${l}\"`)\n .join(\", \");\n\n const content = `const { defineConfig } = require(\"@lobehub/i18n-cli\");\n\nmodule.exports = defineConfig({\n entry: \"${localesDir}/${defaultLocale}\",\n entryLocale: \"${defaultLocale}\",\n output: \"${localesDir}\",\n outputLocales: [${outputLocales}],\n});\n`;\n\n writeFileSync(filePath, content, \"utf-8\");\n logger.info(\"已生成翻译配置: .i18nrc.js(@lobehub/i18n-cli)\");\n}\n\n// ============ 脚手架:非默认语言的 JSON 目录 ============\n\nfunction scaffoldLocaleJsonDirs(\n cwd: string,\n localesDir: string,\n locales: string[],\n defaultLocale: string,\n namespaces: string[],\n logger: { info: (msg: string) => void },\n): void {\n const baseDir = join(cwd, localesDir);\n\n for (const locale of locales) {\n const localeDir = join(baseDir, locale);\n if (!existsSync(localeDir)) {\n mkdirSync(localeDir, { recursive: true });\n }\n\n // 只为非默认语言生成占位 JSON(默认语言由脚本从 TS 生成)\n if (locale === defaultLocale) continue;\n\n for (const ns of namespaces) {\n const filePath = join(localeDir, `${ns}.json`);\n if (!existsSync(filePath)) {\n const placeholder =\n ns === \"common\"\n ? JSON.stringify(\n {\n welcome: \"Welcome\",\n loading: \"Loading...\",\n confirm: \"OK\",\n cancel: \"Cancel\",\n save: \"Save\",\n delete: \"Delete\",\n edit: \"Edit\",\n back: \"Back\",\n },\n null,\n 2,\n )\n : JSON.stringify({ title: ns }, null, 2);\n writeFileSync(filePath, `${placeholder}\\n`, \"utf-8\");\n logger.info(`已生成翻译文件: ${localesDir}/${locale}/${ns}.json`);\n }\n }\n }\n}\n\nexport default i18nPlugin;\n","import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { createPlugin } from \"../define.js\";\nimport type { PluginHooks } from \"../types.js\";\n\nexport interface MockPluginOptions {\n /** Mock 文件目录 */\n mockDir?: string;\n /** 是否在生产环境启用 */\n enableInProd?: boolean;\n /** 延迟时间(模拟网络延迟) */\n delay?: number;\n /** 前缀路径 */\n prefix?: string;\n}\n\n/**\n * Mock 数据插件\n *\n * @example\n * ```ts\n * // ywkf.config.ts\n * import { mockPlugin } from \"@4399ywkf/core/plugin\";\n *\n * export default defineConfig({\n * plugins: [\n * mockPlugin({\n * mockDir: \"mock\",\n * prefix: \"/api\",\n * }),\n * ],\n * });\n * ```\n *\n * Mock 文件示例 (mock/user.ts):\n * ```ts\n * export default {\n * \"GET /api/users\": [\n * { id: 1, name: \"张三\" },\n * ],\n * \"POST /api/users\": (req, res) => {\n * res.json({ success: true });\n * },\n * };\n * ```\n */\nexport const mockPlugin = createPlugin<MockPluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-mock\",\n version: \"1.0.0\",\n description: \"Mock 数据插件\",\n\n setup(context) {\n const { mockDir = \"mock\", enableInProd = false, delay = 0, prefix = \"\" } = options;\n const { cwd, isDev, logger } = context;\n\n // 生产环境且未启用则跳过\n if (!isDev && !enableInProd) {\n logger.info(\"生产环境已禁用 Mock\");\n return {};\n }\n\n const mockPath = resolve(cwd, mockDir);\n\n // 检查 mock 目录是否存在\n if (!existsSync(mockPath)) {\n logger.warn(`Mock 目录不存在: ${mockPath}`);\n return {};\n }\n\n const hooks: PluginHooks = {\n modifyRspackConfig(rspackConfig) {\n // 配置 devServer proxy 以支持 mock\n if (isDev && rspackConfig.devServer) {\n const mockFiles = scanMockFiles(mockPath);\n logger.info(`找到 ${mockFiles.length} 个 Mock 文件`);\n\n // 添加 mock 中间件配置\n rspackConfig.devServer.setupMiddlewares = (middlewares, _devServer) => {\n // 在其他中间件之前添加 mock 处理\n middlewares.unshift({\n name: \"mock-middleware\",\n middleware: createMockMiddleware(mockPath, { delay, prefix, logger }),\n });\n return middlewares;\n };\n }\n\n return rspackConfig;\n },\n\n beforeDevServer() {\n logger.info(`Mock 已启用,目录: ${mockPath}`);\n if (delay > 0) {\n logger.info(`模拟延迟: ${delay}ms`);\n }\n },\n };\n\n return hooks;\n },\n}));\n\n/**\n * 扫描 mock 文件\n */\nfunction scanMockFiles(dir: string): string[] {\n const files: string[] = [];\n\n if (!existsSync(dir)) {\n return files;\n }\n\n const entries = readdirSync(dir);\n\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const stat = statSync(fullPath);\n\n if (stat.isFile() && /\\.(ts|js|mjs)$/.test(entry)) {\n files.push(fullPath);\n } else if (stat.isDirectory()) {\n files.push(...scanMockFiles(fullPath));\n }\n }\n\n return files;\n}\n\n/**\n * 创建 mock 中间件\n */\nfunction createMockMiddleware(\n mockPath: string,\n options: { delay: number; prefix: string; logger: { info: (msg: string) => void } },\n): (req: unknown, res: unknown, next: () => void) => Promise<void> {\n const { delay } = options;\n\n // 加载所有 mock 文件\n scanMockFiles(mockPath);\n\n return async (_req: unknown, _res: unknown, next: () => void) => {\n // 简化实现:实际应该加载 mock 文件并匹配请求\n // 这里直接传递给下一个中间件\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n next();\n };\n}\n\nexport default mockPlugin;\n","import { createPlugin } from \"../define.js\";\nimport type { CodeInjection, GeneratedFile, GeneratorContext, PluginHooks } from \"../types.js\";\n\nexport interface ReactQueryPluginOptions {\n /**\n * 默认 staleTime(毫秒)\n * @default 5 * 60 * 1000 (5 分钟)\n */\n staleTime?: number;\n\n /**\n * 默认 gcTime(毫秒)\n * @default 10 * 60 * 1000 (10 分钟)\n */\n gcTime?: number;\n\n /**\n * 默认重试次数\n * @default 1\n */\n retry?: number | boolean;\n\n /**\n * 是否开启 React Query DevTools(仅开发模式生效)\n * @default true\n */\n devtools?: boolean;\n\n /**\n * axios baseURL\n * @default \"\"\n */\n baseURL?: string;\n\n /**\n * 请求超时时间(毫秒)\n * @default 15000\n */\n timeout?: number;\n}\n\n/**\n * React Query + Axios 请求层插件\n *\n * - 自动注入 QueryClientProvider\n * - 生成 .ywkf/query-client.ts(QueryClient 实例 + 默认配置)\n * - 生成 .ywkf/request.ts(axios 封装 + 拦截器骨架)\n * - 开发模式可选开启 React Query DevTools\n *\n * @example\n * ```ts\n * import { defineConfig, reactQueryPlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * reactQueryPlugin({ staleTime: 5 * 60 * 1000 }),\n * ],\n * });\n * ```\n */\nexport const reactQueryPlugin = createPlugin<ReactQueryPluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-react-query\",\n version: \"1.0.0\",\n description: \"React Query + Axios 请求层集成\",\n\n setup(context) {\n const {\n staleTime = 5 * 60 * 1000,\n gcTime = 10 * 60 * 1000,\n retry = 1,\n devtools = true,\n baseURL = \"\",\n timeout = 15000,\n } = options;\n\n const { logger, isDev } = context;\n\n const hooks: PluginHooks = {\n generateFiles(_ctx: GeneratorContext): GeneratedFile[] {\n logger.info(\"React Query 已启用\");\n\n const files: GeneratedFile[] = [\n {\n path: \"query-client.ts\",\n content: buildQueryClientFile({ staleTime, gcTime, retry, devtools, isDev }),\n },\n {\n path: \"request.ts\",\n content: buildRequestFile({ baseURL, timeout }),\n },\n ];\n\n return files;\n },\n\n injectBootstrap(_ctx: GeneratorContext): CodeInjection {\n return {\n imports: [\n `import { QueryClientProvider } from \"@tanstack/react-query\";`,\n `import { queryClient } from \"./query-client\";`,\n ],\n topLevel: [`// React Query Provider(由 @4399ywkf/plugin-react-query 注入)`],\n };\n },\n\n modifyBootstrapCode(code: string): string {\n // 在 createAppConfig 的 providers 数组中注入 QueryClientProvider\n const providerEntry = ` {\n component: QueryClientProvider as React.ComponentType<{ children: React.ReactNode }>,\n props: { client: queryClient },\n order: 20,\n }`;\n\n // 查找 providers: [] 并注入\n if (code.includes(\"providers: []\")) {\n code = code.replace(\"providers: []\", `providers: [\\n${providerEntry},\\n ]`);\n } else if (code.includes(\"providers: [\")) {\n code = code.replace(\"providers: [\", `providers: [\\n${providerEntry},`);\n }\n\n // 补充 React import(用于类型断言)\n if (!code.includes(\"import React\")) {\n code = code.replace(\n `import { bootstrap`,\n `import React from \"react\";\\nimport { bootstrap`,\n );\n }\n\n return code;\n },\n };\n\n return hooks;\n },\n}));\n\nfunction buildQueryClientFile(opts: {\n staleTime: number;\n gcTime: number;\n retry: number | boolean;\n devtools: boolean;\n isDev: boolean;\n}): string {\n const { staleTime, gcTime, retry, devtools, isDev } = opts;\n\n return `// 此文件由 @4399ywkf/plugin-react-query 自动生成\nimport { QueryClient } from \"@tanstack/react-query\";\n\n/**\n * 全局 QueryClient 实例\n *\n * 默认配置可在 ywkf.config.ts 的 reactQueryPlugin 选项中修改。\n * 运行时自定义可通过 src/app.config.ts 覆盖。\n */\nexport const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: ${staleTime},\n gcTime: ${gcTime},\n retry: ${typeof retry === \"boolean\" ? retry : retry},\n refetchOnWindowFocus: false,\n },\n mutations: {\n retry: false,\n },\n },\n});\n\nexport default queryClient;\n`;\n}\n\nfunction buildRequestFile(opts: { baseURL: string; timeout: number }): string {\n const { baseURL, timeout } = opts;\n\n return `// 此文件由 @4399ywkf/plugin-react-query 自动生成,请勿手动修改\n// 如需定制拦截器,请编辑 src/request.ts\nimport axios from \"axios\";\nimport qs from \"qs\";\nimport type { AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from \"axios\";\nimport type { RequestConfig, Result } from \"@4399ywkf/core/runtime\";\n\n// ============ 加载用户配置 ============\n\nlet userConfig: RequestConfig = {};\n\ntry {\n const mod = require(\"@/request\");\n userConfig = mod.default || mod;\n} catch {\n // src/request.ts 不存在,使用默认配置\n}\n\n// ============ 参数序列化(GET 请求专用)============\n\n/**\n * GET 请求参数序列化规则:\n * - 数组:repeat 模式(key=1&key=2)\n * - 对象:JSON.stringify 后作为字符串传递\n * - null / undefined:skipNulls 跳过\n * - 基本类型:原样传递\n */\nexport function paramsSerializer(params: Record<string, any>): string {\n const normalized: Record<string, any> = {};\n\n Object.keys(params).forEach((key) => {\n const value = params[key];\n\n if (value === null || value === undefined) {\n normalized[key] = value;\n } else if (Array.isArray(value)) {\n normalized[key] = value;\n } else if (typeof value === \"object\") {\n normalized[key] = JSON.stringify(value);\n } else {\n normalized[key] = value;\n }\n });\n\n return qs.stringify(normalized, { arrayFormat: \"repeat\", skipNulls: true });\n}\n\n// ============ 创建 Axios 实例 ============\n\nconst instance: AxiosInstance = axios.create({\n baseURL: userConfig.baseURL ?? (\"${baseURL}\" || \"\"),\n timeout: userConfig.timeout ?? ${timeout},\n withCredentials: userConfig.withCredentials ?? false,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(userConfig.headers || {}),\n },\n});\n\n// ============ 请求拦截器 ============\n\ninstance.interceptors.request.use(\n (config: InternalAxiosRequestConfig) => {\n // 1. Token 注入\n if (userConfig.getToken) {\n const token = userConfig.getToken();\n if (token && config.headers) {\n const prefix = userConfig.tokenPrefix ?? \"Bearer\";\n config.headers.Authorization = prefix ? \\`\\${prefix} \\${token}\\` : token;\n }\n } else {\n // 默认:从 localStorage 读取\n const token = typeof localStorage !== \"undefined\"\n ? localStorage.getItem(\"token\")\n : null;\n if (token && config.headers) {\n config.headers.Authorization = \\`Bearer \\${token}\\`;\n }\n }\n\n // 2. 用户自定义请求拦截\n if (userConfig.requestInterceptor) {\n return userConfig.requestInterceptor(config as any) as any;\n }\n\n return config;\n },\n (error: AxiosError) => Promise.reject(error)\n);\n\n// ============ 响应拦截器 ============\n\ninstance.interceptors.response.use(\n (response: AxiosResponse) => {\n // 用户自定义响应拦截\n if (userConfig.responseInterceptor) {\n return userConfig.responseInterceptor(response as any);\n }\n\n // 默认:直接返回 response.data\n return response.data;\n },\n (error: AxiosError) => {\n // 用户自定义错误处理\n if (userConfig.errorHandler) {\n return userConfig.errorHandler(error as any);\n }\n\n // 默认错误处理\n const status = error.response?.status;\n\n switch (status) {\n case 401:\n console.warn(\"[request] 未授权,请重新登录\");\n break;\n case 403:\n console.warn(\"[request] 无访问权限\");\n break;\n case 500:\n console.error(\"[request] 服务器内部错误\");\n break;\n default:\n if (!error.response) {\n console.error(\"[request] 网络异常,请检查网络连接\");\n }\n }\n\n return Promise.reject(error);\n }\n);\n\n// ============ 请求封装类 ============\n\ntype ExtraConfig = AxiosRequestConfig & { suppressErrorNotification?: boolean };\n\nclass Request {\n constructor(private readonly http: AxiosInstance) {}\n\n get<T = any>(url: string, params?: Record<string, any>, config?: ExtraConfig): Promise<Result<T>> {\n return this.http.get(url, {\n ...config,\n params,\n paramsSerializer,\n });\n }\n\n post<T = any>(url: string, data?: any, config?: ExtraConfig): Promise<Result<T>> {\n return this.http.post(url, data, config);\n }\n\n put<T = any>(url: string, data?: any, config?: ExtraConfig): Promise<Result<T>> {\n return this.http.put(url, data, config);\n }\n\n delete<T = any>(url: string, params?: Record<string, any>, config?: ExtraConfig): Promise<Result<T>> {\n return this.http.delete(url, {\n ...config,\n params,\n paramsSerializer,\n });\n }\n\n patch<T = any>(url: string, data?: any, config?: ExtraConfig): Promise<Result<T>> {\n return this.http.patch(url, data, config);\n }\n}\n\n// ============ 导出 ============\n\nexport const request = new Request(instance);\nexport type { Result };\nexport default request;\n`;\n}\n\nexport default reactQueryPlugin;\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { rspack } from \"@rspack/core\";\nimport { createPlugin } from \"../define.js\";\nimport type { CodeInjection, GeneratedFile, GeneratorContext, PluginHooks } from \"../types.js\";\n\nexport interface TailwindPluginOptions {\n /**\n * 自定义暗色模式选择器\n * @default '&:where([data-theme=\"dark\"], [data-theme=\"dark\"] *)'\n */\n darkModeSelector?: string;\n\n /**\n * 是否生成 postcss.config.js(如果不存在)\n * @default true\n */\n autoConfig?: boolean;\n\n /**\n * 额外的 CSS 内容(追加到 index.css 之后)\n */\n extraCSS?: string;\n}\n\n/**\n * Tailwind CSS 插件\n *\n * 自动配置 Tailwind CSS:\n * - 注入 `@import \"tailwindcss\"` 到 index.css\n * - 确保 postcss.config.js 存在\n * - 修改 Rspack 配置添加 postcss-loader\n *\n * @example\n * ```ts\n * import { defineConfig, tailwindPlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * tailwindPlugin(),\n * ],\n * });\n * ```\n */\nexport const tailwindPlugin = createPlugin<TailwindPluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-tailwind\",\n version: \"1.0.0\",\n description: \"Tailwind CSS 集成插件\",\n\n setup(context) {\n const {\n darkModeSelector = '&:where([data-theme=\"dark\"], [data-theme=\"dark\"] *)',\n autoConfig = true,\n extraCSS = \"\",\n } = options;\n const { cwd, logger } = context;\n\n // 确保 postcss.config.js 存在\n if (autoConfig) {\n ensurePostcssConfig(cwd, logger);\n }\n\n const hooks: PluginHooks = {\n modifyRspackConfig(rspackConfig) {\n logger.info(\"Tailwind CSS 已启用\");\n\n // 在 module.rules 中添加 .ywkf/tailwind.css 的 postcss-loader 规则\n const rules = rspackConfig.module?.rules || [];\n const postcssConfigPath = join(cwd, \"postcss.config.js\");\n\n // 根据 mode 选择 style-loader 或 CssExtractRspackPlugin.loader\n const isProd = rspackConfig.mode === \"production\";\n\n const tailwindRule = {\n test: /tailwind\\.css$/,\n use: [\n isProd ? rspack.CssExtractRspackPlugin.loader : \"style-loader\",\n \"css-loader\",\n {\n loader: \"postcss-loader\",\n options: {\n postcssOptions: {\n config: postcssConfigPath,\n },\n },\n },\n ],\n };\n\n rules.unshift(tailwindRule);\n rspackConfig.module = { ...rspackConfig.module, rules };\n\n return rspackConfig;\n },\n\n generateFiles(_ctx: GeneratorContext): GeneratedFile[] {\n const cssContent = buildTailwindCSS(darkModeSelector, extraCSS);\n return [\n {\n path: \"tailwind.css\",\n content: cssContent,\n },\n ];\n },\n\n injectEntry(_ctx: GeneratorContext): CodeInjection {\n return {\n imports: [`import \"./tailwind.css\";`],\n };\n },\n };\n\n return hooks;\n },\n}));\n\nfunction buildTailwindCSS(darkModeSelector: string, extraCSS: string): string {\n return `/* 此文件由 @4399ywkf/plugin-tailwind 自动生成 */\n@import \"tailwindcss\";\n@variant dark (${darkModeSelector});\n${extraCSS ? `\\n${extraCSS}` : \"\"}\n`;\n}\n\nfunction ensurePostcssConfig(cwd: string, logger: { info: (msg: string) => void }): void {\n const configPath = join(cwd, \"postcss.config.js\");\n if (!existsSync(configPath)) {\n writeFileSync(\n configPath,\n `module.exports = {\\n plugins: {\\n \"@tailwindcss/postcss\": {},\\n },\\n};\\n`,\n \"utf-8\",\n );\n logger.info(\"已自动生成 postcss.config.js\");\n }\n}\n\nexport default tailwindPlugin;\n","import { join } from \"node:path\";\nimport { createPlugin } from \"../define.js\";\nimport type {\n CodeInjection,\n GeneratedFile,\n GeneratorContext,\n PluginHooks,\n} from \"../types.js\";\n\nexport interface ThemePluginOptions {\n /**\n * 是否启用暗色模式切换能力\n * @default true\n */\n darkMode?: boolean;\n\n /**\n * 默认主题模式(运行时可通过 useThemeStore 动态切换)\n * @default \"light\"\n */\n defaultAppearance?: \"light\" | \"dark\" | \"auto\";\n\n /**\n * 主色调(Lobe-UI 命名预设,运行时可通过 useThemeStore 动态切换)\n *\n * 不设置时使用 Lobe-UI 默认 primary 色阶(黑色系),\n * 可选值:\"blue\" | \"cyan\" | \"geekblue\" | \"gold\" | \"green\" | \"lime\"\n * | \"magenta\" | \"orange\" | \"purple\" | \"red\" | \"volcano\" | \"yellow\"\n *\n * @default undefined\n */\n primaryColor?: string;\n\n /**\n * 中性色(Lobe-UI 命名预设)\n *\n * 可选值:\"mauve\" | \"olive\" | \"sage\" | \"sand\" | \"slate\"\n *\n * @default undefined\n */\n neutralColor?: string;\n\n /**\n * antd 组件前缀\n *\n * 支持三种配置方式(优先级从高到低):\n * 1. 运行时环境变量 process.env.YWKF_PREFIX_CLS\n * 2. 插件选项中直接指定\n * 3. 默认值 \"ant\"\n *\n * @default \"ant\"\n */\n prefixCls?: string;\n\n /**\n * 是否启用 CSS 变量\n * @default true\n */\n cssVar?: boolean;\n\n /**\n * 是否注入全局样式重置\n * @default true\n */\n globalReset?: boolean;\n\n /**\n * 是否启用外部主题注入(微前端场景)\n *\n * 启用后:\n * - 应用启动时读取 window.__YWKF_THEME__ 作为初始覆盖\n * - 监听 ywkf:theme-change 自定义事件,实现运行时主题同步\n *\n * @default false\n */\n externalTheme?: boolean;\n\n /**\n * antd 国际化 locale 配置\n *\n * - `\"auto\"`(默认):运行时自动检测并动态加载对应的 antd 语言包,兜底 zhCN。\n * 检测优先级:`window.__YWKF_LOCALE__`(微前端注入)> `navigator.language` > `\"zh-CN\"`\n *\n * auto 模式下 locale 被纳入 ThemeStore,支持:\n * - 用户代码通过 `useThemeStore.getState().setLocale(\"en-US\")` 运行时切换\n * - 微前端主应用通过 `ywkf:locale-change` 自定义事件同步 locale\n * - 便捷 hook `useLocale()` 获取当前 locale(BCP 47 tag)\n *\n * - 指定具体名称(如 `\"zhCN\"` / `\"enUS\"`):静态导入该语言包,无运行时开销,\n * locale 仍会写入 ThemeStore 但不会自动检测或监听外部事件\n *\n * @default \"auto\"\n */\n locale?: \"zhCN\" | \"enUS\" | \"zhTW\" | \"jaJP\" | \"koKR\" | \"auto\";\n\n /**\n * 将 Tooltip / Dropdown / Modal 等弹层的挂载节点限定在 ThemeWrapper 容器内\n *\n * 解决问题:antd 弹层默认挂载到 document.body,在以下场景会导致样式失效:\n * - 微前端子应用使用 StyleProvider 将样式注入到子应用容器,弹层挂载 body 后脱离样式范围\n * - CSS 变量作用域被限定在特定容器,body 上的弹层无法继承\n *\n * 启用后会在 ThemeWrapper 内创建一个 `data-ywkf-root` 容器作为弹层挂载点,\n * 该容器始终是 StyleProvider 的子孙节点,样式链路不会断裂。\n *\n * @default true\n */\n scopePopupContainer?: boolean;\n\n}\n\n/**\n * 响应式主题系统插件\n *\n * 基于 antd-style + @4399ywkf/theme-system + Zustand 提供运行时可变的主题管理:\n * - 使用 Lobe-UI 色彩体系(13 阶色阶 + 自定义算法)\n * - 支持 PrimaryColors / NeutralColors 命名预设\n * - 亮/暗色/跟随系统自动切换\n * - 支持微前端场景主应用注入主题\n *\n * @example\n * ```ts\n * import { defineConfig, themePlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * themePlugin({\n * defaultAppearance: \"light\",\n * primaryColor: \"geekblue\",\n * neutralColor: \"slate\",\n * prefixCls: \"my-app\",\n * }),\n * ],\n * });\n * ```\n */\nexport const themePlugin = createPlugin<ThemePluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-theme\",\n version: \"3.0.0\",\n description: \"Lobe-UI 风格响应式主题系统插件\",\n\n setup(context) {\n const {\n darkMode = true,\n defaultAppearance = \"light\",\n primaryColor,\n neutralColor,\n prefixCls = \"ant\",\n cssVar = true,\n globalReset = true,\n externalTheme = false,\n locale = \"auto\",\n scopePopupContainer = true,\n } = options;\n const { logger } = context;\n\n logger.info(\n `主题模式: ${defaultAppearance}, 主色: ${\n primaryColor ?? \"primary(默认黑)\"\n }, 响应式: ✓`,\n );\n\n const hooks: PluginHooks = {\n modifyRspackConfig(config, ctx) {\n const themePath = join(ctx.cwd, \".ywkf\", \"theme.tsx\");\n const currentAlias = (config.resolve?.alias ?? {}) as Record<\n string,\n string\n >;\n config.resolve = {\n ...config.resolve,\n alias: {\n ...currentAlias,\n \"@ywkf/theme\": themePath,\n },\n };\n return config;\n },\n\n generateFiles(_ctx: GeneratorContext): GeneratedFile[] {\n return [\n {\n path: \"theme.tsx\",\n content: generateThemeProvider({\n darkMode,\n defaultAppearance,\n primaryColor,\n neutralColor,\n prefixCls,\n cssVar,\n globalReset,\n externalTheme,\n locale,\n scopePopupContainer,\n }),\n },\n ];\n },\n\n injectBootstrap(_ctx: GeneratorContext): CodeInjection {\n return {\n imports: [`import { ThemeWrapper } from \"./theme\";`],\n };\n },\n\n modifyBootstrapCode(code: string): string {\n const providerEntry = ` {\n component: ThemeWrapper as React.ComponentType<{ children: React.ReactNode }>,\n props: {},\n order: 10,\n }`;\n\n if (code.includes(\"providers: []\")) {\n code = code.replace(\n \"providers: []\",\n `providers: [\\n${providerEntry},\\n ]`,\n );\n } else if (code.includes(\"providers: [\")) {\n code = code.replace(\n \"providers: [\",\n `providers: [\\n${providerEntry},`,\n );\n }\n\n if (!code.includes(\"import React\")) {\n code = code.replace(\n `import { bootstrap`,\n `import React from \"react\";\\nimport { bootstrap`,\n );\n }\n\n return code;\n },\n };\n\n return hooks;\n },\n}));\n\n// ═══════════════════════════════════════════════════════════\n// Code Generator\n// ═══════════════════════════════════════════════════════════\n\ninterface GenerateOptions {\n darkMode: boolean;\n defaultAppearance: string;\n primaryColor?: string;\n neutralColor?: string;\n prefixCls: string;\n cssVar: boolean;\n globalReset: boolean;\n externalTheme: boolean;\n locale: string;\n scopePopupContainer: boolean;\n}\n\nfunction generateThemeProvider(opts: GenerateOptions): string {\n const {\n darkMode,\n defaultAppearance,\n primaryColor,\n neutralColor,\n prefixCls,\n cssVar,\n globalReset,\n externalTheme,\n locale,\n scopePopupContainer,\n } = opts;\n\n const isAutoLocale = locale === \"auto\";\n const sections: string[] = [];\n\n sections.push(`// 此文件由 @4399ywkf/plugin-theme v3 自动生成,请勿手动修改`);\n sections.push(buildImports({ globalReset, cssVar, scopePopupContainer, locale }));\n sections.push(TYPES_CODE);\n sections.push(\n buildStoreCode({ defaultAppearance, primaryColor, neutralColor, locale }),\n );\n sections.push(HOOKS_CODE);\n\n if (globalReset) sections.push(GLOBAL_RESET_CODE);\n if (cssVar) sections.push(buildCssVarSyncCode());\n if (darkMode) sections.push(APPEARANCE_SYNC_CODE);\n if (externalTheme) sections.push(EXTERNAL_THEME_CODE);\n if (isAutoLocale) sections.push(LOCALE_AUTO_CODE);\n\n sections.push(\n buildWrapperCode({\n darkMode,\n cssVar,\n globalReset,\n externalTheme,\n locale,\n prefixCls,\n scopePopupContainer,\n }),\n );\n\n return sections.join(\"\\n\");\n}\n\n// ── Import Builder ──\n\nconst ANTD_LOCALE_MAP: Record<string, { importName: string; importPath: string }> = {\n zhCN: { importName: \"zhCN\", importPath: \"antd/locale/zh_CN.js\" },\n enUS: { importName: \"enUS\", importPath: \"antd/locale/en_US.js\" },\n zhTW: { importName: \"zhTW\", importPath: \"antd/locale/zh_TW.js\" },\n jaJP: { importName: \"jaJP\", importPath: \"antd/locale/ja_JP.js\" },\n koKR: { importName: \"koKR\", importPath: \"antd/locale/ko_KR.js\" },\n};\n\nconst LOCALE_TO_BCP47: Record<string, string> = {\n zhCN: \"zh-CN\",\n enUS: \"en-US\",\n zhTW: \"zh-TW\",\n jaJP: \"ja-JP\",\n koKR: \"ko-KR\",\n};\n\nfunction buildImports(opts: {\n globalReset: boolean;\n cssVar: boolean;\n scopePopupContainer: boolean;\n locale: string;\n}): string {\n const needsRef = opts.cssVar || opts.scopePopupContainer;\n const isAutoLocale = opts.locale === \"auto\";\n\n const reactImports = [\n \"useCallback\",\n \"useEffect\",\n \"useMemo\",\n \"useState\",\n ...(opts.cssVar ? [\"useLayoutEffect\"] : []),\n ...(needsRef ? [\"useRef\"] : []),\n \"type ReactNode\",\n ];\n\n const antdStyleImports = [\n \"ThemeProvider as AntdThemeProvider\",\n \"StyleProvider\",\n \"type GetAntdTheme\",\n ...(opts.globalReset ? [\"createGlobalStyle\", \"css\"] : []),\n ];\n\n const localeEntry = ANTD_LOCALE_MAP[opts.locale];\n const localeImports = isAutoLocale\n ? `import zhCN from \"antd/locale/zh_CN.js\";\\nimport type { Locale as AntdLocale } from \"antd/es/locale\";`\n : localeEntry\n ? `import ${localeEntry.importName} from \"${localeEntry.importPath}\";`\n : `import zhCN from \"antd/locale/zh_CN.js\";`;\n\n return `\nimport React, { ${reactImports.join(\", \")} } from \"react\";\nimport { ConfigProvider } from \"antd\";\n${localeImports}\nimport { ${antdStyleImports.join(\", \")} } from \"antd-style\";\nimport { createWithEqualityFn } from \"zustand/traditional\";\nimport { shallow } from \"zustand/shallow\";\nimport { createThemeConfig, type PrimaryColors, type NeutralColors } from \"@4399ywkf/theme-system\";`;\n}\n\n// ── Types ──\n\nconst TYPES_CODE = `\n// ═══════════════ Types ═══════════════\n\nexport type ThemeAppearance = \"light\" | \"dark\" | \"auto\";\n\nexport interface ThemeState {\n appearance: ThemeAppearance;\n primaryColor?: PrimaryColors;\n neutralColor?: NeutralColors;\n /** BCP 47 language tag, e.g. \"zh-CN\", \"en-US\" */\n locale: string;\n}\n\nexport interface ThemeActions {\n setAppearance: (mode: ThemeAppearance) => void;\n setPrimaryColor: (color: PrimaryColors | undefined) => void;\n setNeutralColor: (color: NeutralColors | undefined) => void;\n setLocale: (locale: string) => void;\n setTheme: (partial: Partial<ThemeState>) => void;\n}\n\nexport type ThemeStore = ThemeState & ThemeActions;\n\nexport type { PrimaryColors, NeutralColors };`;\n\n// ── Store Builder ──\n\nfunction buildStoreCode(opts: {\n defaultAppearance: string;\n primaryColor?: string;\n neutralColor?: string;\n locale: string;\n}): string {\n const isAutoLocale = opts.locale === \"auto\";\n const primaryLine = opts.primaryColor\n ? ` primaryColor: \"${opts.primaryColor}\" as PrimaryColors,`\n : ` primaryColor: undefined,`;\n const neutralLine = opts.neutralColor\n ? ` neutralColor: \"${opts.neutralColor}\" as NeutralColors,`\n : ` neutralColor: undefined,`;\n\n const localeLine = isAutoLocale\n ? ` locale: detectInitialLocale(),`\n : ` locale: \"${LOCALE_TO_BCP47[opts.locale] ?? \"zh-CN\"}\",`;\n\n const detectionFn = isAutoLocale\n ? `\nfunction detectInitialLocale(): string {\n if (typeof window !== \"undefined\") {\n const hostLocale = (window as any).__YWKF_LOCALE__;\n if (typeof hostLocale === \"string\" && hostLocale) return hostLocale;\n }\n if (typeof navigator !== \"undefined\") {\n return navigator.language || \"zh-CN\";\n }\n return \"zh-CN\";\n}\n`\n : \"\";\n\n return `\n// ═══════════════ Theme Store ═══════════════\n${detectionFn}\nconst DEFAULT_THEME: ThemeState = {\n appearance: \"${opts.defaultAppearance}\",\n${primaryLine}\n${neutralLine}\n${localeLine}\n};\n\nexport const useThemeStore = createWithEqualityFn<ThemeStore>()(\n (set) => ({\n ...DEFAULT_THEME,\n setAppearance: (mode) => set({ appearance: mode }),\n setPrimaryColor: (color) => set({ primaryColor: color }),\n setNeutralColor: (color) => set({ neutralColor: color }),\n setLocale: (locale) => set({ locale }),\n setTheme: (partial) => set(partial),\n }),\n shallow,\n);`;\n}\n\n// ── Convenience Hooks ──\n\nconst HOOKS_CODE = `\n// ═══════════════ Convenience Hooks ═══════════════\n\nexport const useTheme = () =>\n useThemeStore(\n (s) => ({\n appearance: s.appearance,\n primaryColor: s.primaryColor,\n neutralColor: s.neutralColor,\n }),\n shallow,\n );\n\nexport const useAppearance = () => useThemeStore((s) => s.appearance);\nexport const usePrimaryColor = () => useThemeStore((s) => s.primaryColor);\nexport const useLocale = () => useThemeStore((s) => s.locale);`;\n\n// ── Global Reset Style ──\n\nconst GLOBAL_RESET_CODE = `\n// ═══════════════ Global Style ═══════════════\n\nconst GlobalReset = createGlobalStyle(({ theme }) => css\\`\n :root {\n --font-settings: \"cv01\", \"tnum\", \"kern\";\n --font-variations: \"opsz\" auto, tabular-nums;\n }\n\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n vertical-align: baseline;\n }\n\n * {\n scrollbar-color: \\${theme.colorFill} transparent;\n scrollbar-width: thin;\n }\n\n html {\n overscroll-behavior: none;\n color-scheme: \\${theme.isDarkMode ? \"dark\" : \"light\"};\n }\n\n html, body, #root, #app {\n height: 100%;\n margin: 0;\n padding: 0;\n }\n\n body {\n overflow: hidden auto;\n min-height: 100vh;\n font-family: \\${theme.fontFamily};\n font-size: \\${theme.fontSize}px;\n font-feature-settings: var(--font-settings);\n font-variation-settings: var(--font-variations);\n line-height: 1;\n color: \\${theme.colorTextBase};\n text-size-adjust: none;\n text-rendering: optimizelegibility;\n word-wrap: break-word;\n background-color: \\${theme.colorBgLayout};\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n -webkit-overflow-scrolling: touch;\n -webkit-tap-highlight-color: transparent;\n }\n\n code {\n font-family: \\${theme.fontFamilyCode} !important;\n }\n\n ::selection {\n -webkit-text-fill-color: unset !important;\n }\n\\`);`;\n\n// ── CSS Variable Class Sync ──\n\nfunction buildCssVarSyncCode(): string {\n return `\n// ═══════════════ CSS Variable Sync ═══════════════\n\nconst CSS_VAR_CLASS_RE = /(^|-)css-var(-|$)/;\n\nfunction isCssVarClassName(className: string): boolean {\n return CSS_VAR_CLASS_RE.test(className);\n}\n\nfunction useCssVarSync(ref: React.RefObject<HTMLDivElement | null>) {\n useLayoutEffect(() => {\n const node = ref.current;\n if (!node) return;\n\n const htmlEl = document.documentElement;\n let currentClasses: string[] = [];\n\n const sync = () => {\n for (const cls of currentClasses) {\n htmlEl.classList.remove(cls);\n }\n\n const nextSet = new Set<string>();\n let el: HTMLElement | null = node;\n\n while (el && el !== htmlEl) {\n for (const cls of el.classList) {\n if (isCssVarClassName(cls)) {\n nextSet.add(cls);\n }\n }\n el = el.parentElement;\n }\n\n const next = Array.from(nextSet);\n\n for (const cls of next) {\n htmlEl.classList.add(cls);\n }\n\n currentClasses = next;\n };\n\n sync();\n\n const observer = new MutationObserver(sync);\n let el: HTMLElement | null = node;\n while (el && el !== htmlEl) {\n observer.observe(el, { attributeFilter: [\"class\"] });\n el = el.parentElement;\n }\n\n return () => {\n observer.disconnect();\n for (const cls of currentClasses) {\n htmlEl.classList.remove(cls);\n }\n };\n }, []);\n}`;\n}\n\n// ── Appearance Sync ──\n\nconst APPEARANCE_SYNC_CODE = `\n// ═══════════════ Appearance Sync ═══════════════\n\nfunction useAppearanceSync(appearance: ThemeAppearance) {\n useEffect(() => {\n if (appearance !== \"auto\") {\n document.documentElement.dataset.theme = appearance;\n return;\n }\n\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n document.documentElement.dataset.theme = mq.matches ? \"dark\" : \"light\";\n\n function handleChange(e: MediaQueryListEvent) {\n document.documentElement.dataset.theme = e.matches ? \"dark\" : \"light\";\n }\n\n mq.addEventListener(\"change\", handleChange);\n return () => mq.removeEventListener(\"change\", handleChange);\n }, [appearance]);\n}`;\n\n// ── External Theme Injection ──\n\nconst EXTERNAL_THEME_CODE = `\n// ═══════════════ External Theme Injection ═══════════════\n\nfunction useExternalTheme() {\n useEffect(() => {\n const hostTheme = (window as any).__YWKF_THEME__;\n if (hostTheme && typeof hostTheme === \"object\") {\n useThemeStore.getState().setTheme(hostTheme);\n }\n\n const handler = (e: Event) => {\n const detail = (e as CustomEvent<Partial<ThemeState>>).detail;\n if (detail) useThemeStore.getState().setTheme(detail);\n };\n\n window.addEventListener(\"ywkf:theme-change\", handler);\n return () => window.removeEventListener(\"ywkf:theme-change\", handler);\n }, []);\n}`;\n\n// ── Locale Auto-Detection ──\n\nconst LOCALE_AUTO_CODE = `\n// ═══════════════ Locale Runtime Management ═══════════════\n\nconst ANTD_LOCALE_LOADERS: Record<string, () => Promise<{ default: AntdLocale }>> = {\n en: () => import(\"antd/locale/en_US.js\"),\n \"zh-tw\": () => import(\"antd/locale/zh_TW.js\"),\n \"zh-hk\": () => import(\"antd/locale/zh_TW.js\"),\n ja: () => import(\"antd/locale/ja_JP.js\"),\n ko: () => import(\"antd/locale/ko_KR.js\"),\n};\n\nfunction useAntdLocale(): AntdLocale {\n const lang = useThemeStore((s) => s.locale);\n const [antdLocale, setAntdLocale] = useState<AntdLocale>(zhCN);\n\n useEffect(() => {\n const normalized = (lang || \"zh-CN\").toLowerCase();\n\n if (normalized === \"zh\" || normalized === \"zh-cn\") {\n setAntdLocale(zhCN);\n return;\n }\n\n const loader =\n ANTD_LOCALE_LOADERS[normalized] ??\n ANTD_LOCALE_LOADERS[normalized.split(\"-\")[0]];\n\n if (loader) {\n let cancelled = false;\n loader().then((m) => {\n if (!cancelled) setAntdLocale(m.default);\n });\n return () => { cancelled = true; };\n }\n\n setAntdLocale(zhCN);\n }, [lang]);\n\n return antdLocale;\n}\n\nfunction useExternalLocale() {\n useEffect(() => {\n const handler = (e: Event) => {\n const locale = (e as CustomEvent<string>).detail;\n if (typeof locale === \"string\" && locale) {\n useThemeStore.getState().setLocale(locale);\n }\n };\n\n window.addEventListener(\"ywkf:locale-change\", handler);\n return () => window.removeEventListener(\"ywkf:locale-change\", handler);\n }, []);\n}`;\n\n// ── Wrapper Builder ──\n\nfunction buildWrapperCode(opts: {\n darkMode: boolean;\n cssVar: boolean;\n globalReset: boolean;\n externalTheme: boolean;\n locale: string;\n prefixCls: string;\n scopePopupContainer: boolean;\n}): string {\n const { darkMode, cssVar, globalReset, externalTheme, locale, prefixCls, scopePopupContainer } = opts;\n\n const cssVarRefLine = cssVar\n ? \"\\n const containerRef = useRef<HTMLDivElement>(null);\"\n : \"\";\n // 弹层挂载容器 ref,与 cssVar 的 containerRef 各司其职:\n // containerRef(display: contents)负责 CSS 变量类名同步,\n // popupContainerRef(position: relative)作为弹层的实际 DOM 挂载点。\n const popupRefLine = scopePopupContainer\n ? \"\\n const popupContainerRef = useRef<HTMLDivElement>(null);\"\n : \"\";\n\n const cssVarSyncLine = cssVar ? \"\\n useCssVarSync(containerRef);\" : \"\";\n const appearanceSyncLine = darkMode\n ? \"\\n useAppearanceSync(appearance);\"\n : \"\";\n const externalThemeLine = externalTheme ? \"\\n useExternalTheme();\" : \"\";\n\n const isAutoLocale = locale === \"auto\";\n const localeEntry = ANTD_LOCALE_MAP[locale];\n const localeVarName = isAutoLocale ? \"antdLocale\" : (localeEntry?.importName ?? \"zhCN\");\n const localeLine = isAutoLocale\n ? \"\\n const antdLocale = useAntdLocale();\\n useExternalLocale();\"\n : \"\";\n\n const getPopupContainerLine = scopePopupContainer\n ? `\\n // 将弹层挂载到容器内部,确保能继承 StyleProvider 注入的样式与 CSS 变量。\n // 微前端模式下优先使用 styleContainer(子应用根容器),\n // 普通模式下使用 popupContainerRef 所指向的包装 div。\n const getPopupContainer = useCallback(\n (): HTMLElement =>\n (IS_MICRO_APP ? styleContainer : popupContainerRef.current) ?? document.body,\n [styleContainer],\n );`\n : \"\";\n\n const childrenSlot = cssVar\n ? `<div ref={containerRef} style={{ display: \"contents\" }}>\n {children}\n </div>`\n : \"{children}\";\n\n // AntdThemeProvider(antd-style ThemeProvider)不透传 getPopupContainer 和 locale,\n // 因此用内层原生 ConfigProvider 承载弹层挂载点及 locale。\n // garfish 子应用会禁用 RootProvider 中的 ConfigProvider(含 locale),\n // 这里统一注入 locale 确保 antd 组件在任何部署模式下都有正确的国际化。\n const innerContent = scopePopupContainer\n ? `<ConfigProvider locale={${localeVarName}} getPopupContainer={getPopupContainer}>\n ${globalReset ? \"<GlobalReset />\" : \"\"}\n ${childrenSlot}\n </ConfigProvider>`\n : `<ConfigProvider locale={${localeVarName}}>\n ${globalReset ? \"<GlobalReset />\" : \"\"}\n ${childrenSlot}\n </ConfigProvider>`;\n\n const antdProvider = `<AntdThemeProvider\n prefixCls={RUNTIME_PREFIX_CLS}\n appearance={resolvedAppearance}\n themeMode={appearance}\n theme={theme}${cssVar ? \"\\n customToken={{ cssVar: true }}\" : \"\"}\n >\n ${innerContent}\n </AntdThemeProvider>`;\n\n // 弹层挂载容器:position relative 为弹层绝对定位提供包含块,\n // overflow visible(默认)允许弹层溢出自身边界正常展示,\n // height 100% 保证与父容器等高,不破坏全局高度链路(GlobalReset 已确保 html/body/#root 100%)。\n const wrapperOpen = scopePopupContainer\n ? `<div\n ref={popupContainerRef}\n data-ywkf-root\n style={{ position: \"relative\", height: \"100%\" }}\n >`\n : \"\";\n const wrapperClose = scopePopupContainer ? `</div>` : \"\";\n\n const innerReturn = `IS_MICRO_APP && styleContainer ? (\n <StyleProvider container={styleContainer}>{provider}</StyleProvider>\n ) : provider`;\n\n const returnBody = scopePopupContainer\n ? `(\n ${wrapperOpen}\n {IS_MICRO_APP && styleContainer ? (\n <StyleProvider container={styleContainer}>{provider}</StyleProvider>\n ) : provider}\n ${wrapperClose}\n )`\n : `(${innerReturn})`;\n\n return `\n// ═══════════════ ThemeWrapper ═══════════════\n\n// 运行时判断是否处于 Garfish 子应用环境,同一 bundle 支持独立部署与微前端两种模式。\nconst IS_MICRO_APP = typeof window !== \"undefined\" && !!(window as any).__GARFISH__;\n\nconst RUNTIME_PREFIX_CLS = typeof process !== \"undefined\"\n && process.env?.YWKF_PREFIX_CLS\n || \"${prefixCls}\";\n\ninterface ThemeWrapperProps {\n children: ReactNode;\n}\n\nexport function ThemeWrapper({ children }: ThemeWrapperProps) {${cssVarRefLine}${popupRefLine}\n const { appearance, primaryColor, neutralColor } = useThemeStore(\n (s) => ({ appearance: s.appearance, primaryColor: s.primaryColor, neutralColor: s.neutralColor }),\n shallow,\n );${cssVarSyncLine}${appearanceSyncLine}${externalThemeLine}${localeLine}\n\n // 微前端模式下,将 CSS-in-JS 样式注入到 Garfish 子应用容器而非 document.head,\n // 避免与主应用共享的 @ant-design/cssinjs StyleContext 产生冲突。\n // useState lazy initializer 同步读取(Garfish 挂载时容器已提前创建),\n // useEffect 兜底处理极端竞态(如 SSR hydration)。\n const [styleContainer, setStyleContainer] = useState<HTMLElement | undefined>(() => {\n if (!IS_MICRO_APP || typeof document === \"undefined\") return undefined;\n return document.getElementById(RUNTIME_PREFIX_CLS)?.parentElement ?? undefined;\n });\n\n useEffect(() => {\n if (!IS_MICRO_APP) return;\n const el = document.getElementById(RUNTIME_PREFIX_CLS)?.parentElement;\n if (el) setStyleContainer(el);\n }, []);\n\n const resolvedAppearance = useMemo(() => {\n if (appearance !== \"auto\") return appearance;\n if (typeof window === \"undefined\") return \"light\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n }, [appearance]);\n\n const theme = useCallback<GetAntdTheme>(\n (ap) => createThemeConfig({\n appearance: ap as \"light\" | \"dark\",\n primaryColor,\n neutralColor,\n }),\n [primaryColor, neutralColor],\n );\n${getPopupContainerLine}\n const provider = (\n ${antdProvider}\n );\n\n return ${returnBody};\n}\n\nexport default ThemeWrapper;\n`;\n}\n\nexport default themePlugin;\n","import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createPlugin } from \"../define.js\";\nimport type { GeneratedFile, GeneratorContext, PluginHooks } from \"../types.js\";\n\nexport interface ZustandPluginOptions {\n /**\n * 是否自动生成 store 脚手架(仅在 store/ 目录不存在时)\n * @default true\n */\n scaffold?: boolean;\n\n /**\n * store 目录路径(相对于项目根目录)\n * @default \"store\"\n */\n storeDir?: string;\n}\n\n/**\n * Zustand 状态管理插件\n *\n * 采用扁平域/Slice 架构:\n * - store/{domain}/slices/ 按业务域拆分\n * - 每个 slice 拆为 initialState.ts + actions.ts\n * - 域级 store.ts 聚合所有 slice\n * - 使用 StateCreator<Store, [['zustand/devtools', never]], [], Action> 标准范式\n * - 内置 devtools + subscribeWithSelector 中间件\n *\n * @example\n * ```ts\n * import { defineConfig, zustandPlugin } from \"@4399ywkf/core\";\n *\n * export default defineConfig({\n * plugins: [\n * zustandPlugin(),\n * ],\n * });\n * ```\n */\nexport const zustandPlugin = createPlugin<ZustandPluginOptions>((options = {}) => ({\n name: \"@4399ywkf/plugin-zustand\",\n version: \"1.0.0\",\n description: \"Zustand 状态管理集成\",\n\n setup(context) {\n const { scaffold = true, storeDir = \"store\" } = options;\n const { cwd, logger } = context;\n\n const storePath = join(cwd, storeDir);\n\n if (scaffold && !existsSync(storePath)) {\n scaffoldStore(storePath, logger);\n }\n\n const hooks: PluginHooks = {\n modifyRspackConfig(rspackConfig) {\n logger.info(\"Zustand 已启用\");\n\n const resolve = rspackConfig.resolve || {};\n const alias = (resolve.alias || {}) as Record<string, string>;\n alias[\"@store\"] = storePath;\n resolve.alias = alias;\n rspackConfig.resolve = resolve;\n\n return rspackConfig;\n },\n\n generateFiles(_ctx: GeneratorContext): GeneratedFile[] {\n return [\n {\n path: \"store.ts\",\n content: buildStoreHelperFile(),\n },\n ];\n },\n };\n\n return hooks;\n },\n}));\n\nfunction scaffoldStore(storePath: string, logger: { info: (msg: string) => void }): void {\n const dirs = [\n storePath,\n join(storePath, \"middleware\"),\n join(storePath, \"app\"),\n join(storePath, \"app\", \"slices\"),\n join(storePath, \"app\", \"slices\", \"counter\"),\n ];\n\n for (const dir of dirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n // store/middleware/createDevtools.ts\n writeFileSync(join(storePath, \"middleware\", \"createDevtools.ts\"), TPL_CREATE_DEVTOOLS, \"utf-8\");\n\n // store/app/slices/counter/initialState.ts\n writeFileSync(\n join(storePath, \"app\", \"slices\", \"counter\", \"initialState.ts\"),\n TPL_COUNTER_INITIAL_STATE,\n \"utf-8\",\n );\n\n // store/app/slices/counter/actions.ts\n writeFileSync(\n join(storePath, \"app\", \"slices\", \"counter\", \"actions.ts\"),\n TPL_COUNTER_ACTIONS,\n \"utf-8\",\n );\n\n // store/app/initialState.ts\n writeFileSync(join(storePath, \"app\", \"initialState.ts\"), TPL_APP_INITIAL_STATE, \"utf-8\");\n\n // store/app/store.ts\n writeFileSync(join(storePath, \"app\", \"store.ts\"), TPL_APP_STORE, \"utf-8\");\n\n // store/app/index.tsx\n writeFileSync(join(storePath, \"app\", \"index.tsx\"), TPL_APP_INDEX, \"utf-8\");\n\n // store/index.ts\n writeFileSync(join(storePath, \"index.ts\"), TPL_STORE_INDEX, \"utf-8\");\n\n logger.info(\"已生成 store/ 脚手架(Agent/Slice 架构)\");\n}\n\n// ==================== 模板内容 ====================\n\nconst TPL_CREATE_DEVTOOLS = `import type { DevtoolsOptions } from \"zustand/middleware\";\nimport { devtools as devtoolsMiddleware } from \"zustand/middleware\";\nimport type { StateCreator, StoreMutatorIdentifier } from \"zustand/vanilla\";\n\n/**\n * 封装 zustand devtools 中间件\n * 生产环境自动禁用,开发环境启用 trace\n */\nexport const createDevtools =\n (name: string, options?: DevtoolsOptions) =>\n <\n T,\n Mps extends [StoreMutatorIdentifier, unknown][] = [],\n Mcs extends [StoreMutatorIdentifier, unknown][] = [],\n >(\n initializer: StateCreator<T, [...Mps, [\"zustand/devtools\", never]], Mcs>,\n ) =>\n devtoolsMiddleware(initializer, {\n name,\n enabled: process.env.NODE_ENV === \"development\",\n trace: process.env.NODE_ENV === \"development\",\n ...options,\n });\n`;\n\nconst TPL_COUNTER_INITIAL_STATE = `export interface CounterState {\n count: number;\n loading: boolean;\n error: string | null;\n}\n\nexport const initialCounterState: CounterState = {\n count: 0,\n loading: false,\n error: null,\n};\n`;\n\nconst TPL_COUNTER_ACTIONS = `import type { StateCreator } from \"zustand/vanilla\";\nimport type { AppStore } from \"../../store\";\n\nexport interface CounterAction {\n increment: () => void;\n decrement: () => void;\n reset: () => void;\n setLoading: (loading: boolean) => void;\n setError: (error: string | null) => void;\n fetchCount: () => Promise<void>;\n}\n\nexport const createCounterSlice: StateCreator<\n AppStore,\n [[\"zustand/devtools\", never]],\n [],\n CounterAction\n> = (set, get) => ({\n increment: () => set((s) => ({ count: s.count + 1 })),\n decrement: () => set((s) => ({ count: s.count - 1 })),\n reset: () => set({ count: 0, error: null }),\n setLoading: (loading) => set({ loading }),\n setError: (error) => set({ error }),\n\n fetchCount: async () => {\n set({ loading: true, error: null });\n try {\n // 替换为实际 API 调用\n // import request from \"@ywkf/request\";\n // const res = await request.get(\"/api/count\");\n // set({ count: res.data, loading: false });\n await new Promise((r) => setTimeout(r, 500));\n set({ count: 42, loading: false });\n } catch (err) {\n set({\n error: err instanceof Error ? err.message : \"未知错误\",\n loading: false,\n });\n }\n },\n});\n`;\n\nconst TPL_APP_INITIAL_STATE = `import {\n type CounterState,\n initialCounterState,\n} from \"./slices/counter/initialState\";\n\n// ============== 聚合所有 Slice 状态 ============== //\n\nexport type AppStoreState = CounterState;\n\nexport const initialState: AppStoreState = {\n ...initialCounterState,\n};\n`;\n\nconst TPL_APP_STORE = `import { subscribeWithSelector } from \"zustand/middleware\";\nimport { shallow } from \"zustand/shallow\";\nimport { createWithEqualityFn } from \"zustand/traditional\";\nimport type { StateCreator } from \"zustand/vanilla\";\n\nimport { createDevtools } from \"../middleware/createDevtools\";\nimport { type AppStoreState, initialState } from \"./initialState\";\n\nimport {\n type CounterAction,\n createCounterSlice,\n} from \"./slices/counter/actions\";\n\n// ============== 聚合 Store 类型 ============== //\n\nexport type AppStore = AppStoreState & CounterAction;\n\n// ============== 创建 Store ============== //\n\nconst createStore: StateCreator<AppStore, [[\"zustand/devtools\", never]]> = (\n ...parameters\n) => ({\n ...initialState,\n ...createCounterSlice(...parameters),\n});\n\n// ============== 实装 useStore ============== //\n\nconst devtools = createDevtools(\"app\");\n\nexport const useAppStore = createWithEqualityFn<AppStore>()(\n subscribeWithSelector(devtools(createStore)),\n shallow,\n);\n\nexport const getAppStoreState = () => useAppStore.getState();\n`;\n\nconst TPL_APP_INDEX = `export { useAppStore, getAppStoreState } from \"./store\";\nexport type { AppStore } from \"./store\";\nexport { initialState } from \"./initialState\";\nexport type { AppStoreState } from \"./initialState\";\n`;\n\nconst TPL_STORE_INDEX = `/**\n * Store 聚合入口\n *\n * 架构:\n * - store/middleware/ — 中间件(devtools 等)\n * - store/{domain}/ — 每个域代表一个业务子系统\n * - store/{domain}/slices — 每个 slice 拆为 initialState + actions\n *\n * 约束:\n * - initialState:纯数据定义,不含逻辑\n * - actions:同步状态变更 + 异步副作用\n * - slice 之间禁止直接修改彼此状态\n * - 域层负责跨 slice 协调\n */\nexport { useAppStore, getAppStoreState } from \"./app\";\nexport type { AppStore, AppStoreState } from \"./app\";\n`;\n\nfunction buildStoreHelperFile(): string {\n return `// 此文件由 @4399ywkf/plugin-zustand 自动生成\n// 提供 Zustand 工具函数的 re-export,方便业务代码引用\n\nexport { useShallow } from \"zustand/react/shallow\";\nexport type { StateCreator, StoreApi } from \"zustand\";\n`;\n}\n\nexport default zustandPlugin;\n","/**\n * 配置标准化\n *\n * 将用户友好的快捷配置(plugin shorthands、智能字段推导)\n * 转换为框架内部所需的标准化格式,同时保持完全向后兼容。\n */\n\nimport { analyticsPlugin } from \"../plugin/builtin/analytics.js\";\nimport { biomePlugin } from \"../plugin/builtin/biome.js\";\nimport { browserCheckPlugin } from \"../plugin/builtin/browser-check.js\";\nimport { garfishPlugin } from \"../plugin/builtin/garfish.js\";\nimport { i18nPlugin } from \"../plugin/builtin/i18n.js\";\nimport { mockPlugin } from \"../plugin/builtin/mock.js\";\nimport { reactQueryPlugin } from \"../plugin/builtin/react-query.js\";\nimport { tailwindPlugin } from \"../plugin/builtin/tailwind.js\";\nimport { themePlugin } from \"../plugin/builtin/theme.js\";\nimport { zustandPlugin } from \"../plugin/builtin/zustand.js\";\nimport type { PluginConfig, YwkfPlugin } from \"../plugin/types.js\";\nimport type { YwkfConfig } from \"./schema.js\";\n\n// ---------------------------------------------------------------------------\n// 插件快捷键 → 工厂函数的映射\n// ---------------------------------------------------------------------------\n\ninterface PluginMapping {\n key: string;\n factory: (opts?: never) => YwkfPlugin;\n pluginName: string;\n}\n\n/** 默认启用的内置插件(按优先级排列) */\nconst BUILTIN_PLUGINS: PluginMapping[] = [\n { key: \"reactQuery\", factory: reactQueryPlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-react-query\" },\n { key: \"zustand\", factory: zustandPlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-zustand\" },\n { key: \"tailwind\", factory: tailwindPlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-tailwind\" },\n];\n\n/** 可选插件(按推荐顺序排列) */\nconst OPTIONAL_PLUGINS: PluginMapping[] = [\n { key: \"biome\", factory: biomePlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-biome\" },\n { key: \"analytics\", factory: analyticsPlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-analytics\" },\n { key: \"mock\", factory: mockPlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-mock\" },\n { key: \"theme\", factory: themePlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-theme\" },\n { key: \"i18n\", factory: i18nPlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-i18n\" },\n { key: \"garfish\", factory: garfishPlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-garfish\" },\n { key: \"browserCheck\", factory: browserCheckPlugin as PluginMapping[\"factory\"], pluginName: \"@4399ywkf/plugin-browser-check\" },\n];\n\n/** 所有快捷键名称 */\nconst ALL_SHORTHAND_KEYS = new Set([\n ...BUILTIN_PLUGINS.map((p) => p.key),\n ...OPTIONAL_PLUGINS.map((p) => p.key),\n]);\n\n// ---------------------------------------------------------------------------\n// 核心标准化函数\n// ---------------------------------------------------------------------------\n\n/**\n * 标准化用户配置\n *\n * 1. **智能字段推导**:html.title ← appCName, html.mountRoot ← appName\n * 2. **内置插件自动注入**:reactQuery / zustand / tailwind 默认启用\n * 3. **快捷配置转换**:`theme: { darkMode: true }` → `themePlugin({ darkMode: true })`\n * 4. **去重合并**:快捷配置 + plugins 数组合并,同名插件以 plugins 中的为准\n * 5. **清理快捷键**:从配置对象中移除已处理的快捷键\n *\n * 向后兼容:如果用户不使用任何快捷键,行为与之前完全一致。\n */\nexport function normalizeConfig(input: YwkfConfig): YwkfConfig {\n const raw = input as Record<string, unknown>;\n const result = { ...raw };\n\n // ─── 1. 检测是否使用了快捷配置 ───\n const hasShorthands = hasAnyShorthand(result);\n\n // 如果没有使用任何快捷键,直接返回原始配置(完全兼容旧行为,零副作用)\n if (!hasShorthands) {\n return input;\n }\n\n // ─── 2. 智能字段推导(仅快捷模式下启用) ───\n inferFields(result);\n\n const plugins = result.plugins as PluginConfig[] | undefined;\n\n // ─── 3. 收集显式 plugins 中已声明的插件名 ───\n const explicitPlugins = plugins ?? [];\n const explicitNames = collectPluginNames(explicitPlugins);\n\n // ─── 4. 生成快捷配置对应的插件实例 ───\n const shorthandPlugins: YwkfPlugin[] = [];\n\n // 4a. 内置插件(默认启用,除非显式 false 或 plugins 中已声明同名插件)\n for (const { key, factory, pluginName } of BUILTIN_PLUGINS) {\n const value = result[key];\n\n if (explicitNames.has(pluginName)) continue;\n if (value === false) continue;\n if (value === undefined && !hasShorthands) continue;\n\n const opts = typeof value === \"object\" ? value : undefined;\n shorthandPlugins.push(factory(opts as never));\n }\n\n // 4b. 可选插件(默认不启用,需显式配置)\n for (const { key, factory, pluginName } of OPTIONAL_PLUGINS) {\n const value = result[key];\n\n if (value === undefined || explicitNames.has(pluginName)) continue;\n\n const opts = value === true ? undefined : (value as Record<string, unknown>);\n shorthandPlugins.push(factory(opts as never));\n }\n\n // ─── 5. 合并:快捷插件在前 + 显式 plugins 在后(显式声明优先级更高) ───\n result.plugins = [...shorthandPlugins, ...explicitPlugins];\n\n // ─── 6. 清理快捷键,避免传递到下游 ───\n for (const key of ALL_SHORTHAND_KEYS) {\n delete result[key];\n }\n\n return result as YwkfConfig;\n}\n\n// ---------------------------------------------------------------------------\n// 辅助函数\n// ---------------------------------------------------------------------------\n\n/**\n * 智能字段推导\n *\n * - html.title 默认取 appCName\n * - html.mountRoot 默认取 appName\n */\nfunction inferFields(config: Record<string, unknown>): void {\n const html = (config.html ?? {}) as Record<string, unknown>;\n config.html = html;\n\n if (html.title === undefined && config.appCName) {\n html.title = config.appCName;\n }\n if (html.mountRoot === undefined && config.appName) {\n html.mountRoot = config.appName;\n }\n}\n\n/** 检查配置中是否使用了任何插件快捷键 */\nfunction hasAnyShorthand(config: Record<string, unknown>): boolean {\n for (const key of ALL_SHORTHAND_KEYS) {\n if (config[key] !== undefined) {\n return true;\n }\n }\n return false;\n}\n\n/** 收集 plugins 数组中已声明的插件名称 */\nfunction collectPluginNames(plugins: PluginConfig[]): Set<string> {\n const names = new Set<string>();\n for (const p of plugins) {\n if (typeof p === \"object\" && p !== null && \"name\" in p) {\n names.add((p as YwkfPlugin).name);\n }\n }\n return names;\n}\n","import type { Configuration as RspackConfig } from \"@rspack/core\";\nimport type { AnalyticsPluginOptions } from \"../plugin/builtin/analytics.js\";\nimport type { BiomePluginOptions } from \"../plugin/builtin/biome.js\";\nimport type { BrowserCheckPluginOptions } from \"../plugin/builtin/browser-check.js\";\nimport type { GarfishPluginOptions } from \"../plugin/builtin/garfish.js\";\nimport type { I18nPluginOptions } from \"../plugin/builtin/i18n.js\";\nimport type { MockPluginOptions } from \"../plugin/builtin/mock.js\";\nimport type { ReactQueryPluginOptions } from \"../plugin/builtin/react-query.js\";\nimport type { TailwindPluginOptions } from \"../plugin/builtin/tailwind.js\";\nimport type { ThemePluginOptions } from \"../plugin/builtin/theme.js\";\nimport type { ZustandPluginOptions } from \"../plugin/builtin/zustand.js\";\nimport type { PluginConfig } from \"../plugin/types.js\";\n\n/**\n * 开发服务器配置\n */\nexport interface DevServerConfig {\n /** 开发服务器端口 */\n port?: number;\n /** 开发服务器主机 */\n host?: string;\n /** 代理配置 */\n proxy?: Record<string, string | object>;\n /** 是否开启 HTTPS */\n https?: boolean;\n}\n\n/**\n * 输出配置\n */\nexport interface OutputConfig {\n /** 输出目录 */\n path?: string;\n /** 公共路径 */\n publicPath?: string;\n /** 是否清理输出目录 */\n clean?: boolean;\n}\n\n/**\n * HTML 配置\n */\nexport interface HtmlConfig {\n /** 页面标题 */\n title?: string;\n /** HTML 模板路径 */\n template?: string;\n /** favicon 路径 */\n favicon?: string;\n /** 挂载根元素 ID */\n mountRoot?: string;\n}\n\n/**\n * 样式配置\n */\nexport interface StyleConfig {\n /** 是否启用 CSS Modules */\n cssModules?: boolean;\n /** Less 配置 */\n less?: {\n /** 是否启用 */\n enabled?: boolean;\n /** Less 选项 */\n lessOptions?: Record<string, unknown>;\n };\n /** Sass 配置 */\n sass?: {\n /** 是否启用 */\n enabled?: boolean;\n /** Sass 选项 */\n sassOptions?: Record<string, unknown>;\n };\n /** 是否启用 TailwindCSS */\n tailwindcss?: boolean;\n}\n\n/**\n * 路由配置\n */\nexport interface RouterConfig {\n /** 路由基础路径 */\n basename?: string;\n /** 是否启用约定式路由 */\n conventional?: boolean;\n /** 约定式路由扫描目录 */\n pagesDir?: string;\n /** 排除的文件/目录模式 */\n exclude?: (string | RegExp)[];\n /**\n * 懒加载的加载状态配置\n * - `false`:禁用全局默认加载状态(各路由仍可通过 loading.tsx 单独配置)\n * - `{ component: string }`:自定义全局默认加载组件的导入路径\n * - 不配置:使用内置默认加载组件\n *\n * @example\n * // 禁用加载状态\n * loading: false\n *\n * @example\n * // 自定义加载组件\n * loading: { component: \"@/components/Loading\" }\n */\n loading?: false | { component: string };\n}\n\n/**\n * 微前端配置\n */\nexport interface MicroFrontendConfig {\n /** 是否启用微前端模式 */\n enabled?: boolean;\n /** 应用名称(用于 UMD 导出) */\n name?: string;\n /** 微前端框架类型 */\n framework?: \"qiankun\" | \"garfish\";\n}\n\n/**\n * 性能配置\n */\nexport interface PerformanceConfig {\n /** 是否启用 Rsdoctor 分析 */\n rsdoctor?: boolean;\n /** 是否开启代码分割 */\n splitChunks?: boolean;\n /** 是否移除 console */\n dropConsole?: boolean;\n}\n\n/**\n * 工具链配置\n */\nexport interface ToolsConfig {\n /**\n * 自定义 Rspack 配置\n * @param config 当前配置\n * @param context 上下文信息\n * @returns 修改后的配置\n */\n rspack?: (\n config: RspackConfig,\n context: { isDev: boolean; isProd: boolean },\n ) => RspackConfig | undefined;\n}\n\n/**\n * 环境变量配置\n */\nexport interface EnvConfig {\n /** 公共环境变量文件路径 */\n publicEnvFile?: string;\n /** 环境特定的变量文件目录 */\n envDir?: string;\n}\n\n// ---------------------------------------------------------------------------\n// 插件快捷配置\n// ---------------------------------------------------------------------------\n\n/**\n * 内置插件快捷配置\n *\n * 这些插件默认启用,无需手动 import 和声明。\n * 设为 `false` 可禁用,传入配置对象可自定义参数。\n *\n * @example\n * ```ts\n * defineConfig({\n * // 禁用 zustand\n * zustand: false,\n * // 自定义 reactQuery 参数\n * reactQuery: { timeout: 30000 },\n * })\n * ```\n */\nexport interface BuiltinPluginConfig {\n /**\n * React Query + Axios 请求层(默认启用)\n *\n * 设为 `false` 禁用;传入配置对象自定义参数。\n * @default {} (启用,使用默认配置)\n */\n reactQuery?: ReactQueryPluginOptions | false;\n\n /**\n * Zustand 状态管理(默认启用)\n *\n * 设为 `false` 禁用;传入配置对象自定义参数。\n * @default {} (启用,使用默认配置)\n */\n zustand?: ZustandPluginOptions | false;\n\n /**\n * Tailwind CSS(默认启用)\n *\n * 设为 `false` 禁用;传入配置对象自定义参数。\n * @default {} (启用,使用默认配置)\n */\n tailwind?: TailwindPluginOptions | false;\n}\n\n/**\n * 可选插件快捷配置\n *\n * 这些插件默认不启用,配置后自动启用。\n * 设为 `true` 使用默认配置启用,传入配置对象可自定义参数。\n *\n * @example\n * ```ts\n * defineConfig({\n * theme: { darkMode: true, locale: \"auto\" },\n * browserCheck: { fromBrowserslist: true },\n * })\n * ```\n */\nexport interface OptionalPluginConfig {\n /**\n * antd-style 主题系统\n *\n * 设为 `true` 使用默认配置启用,或传入 ThemePluginOptions 自定义。\n */\n theme?: ThemePluginOptions | true;\n\n /**\n * 国际化 (i18next)\n *\n * 设为 `true` 使用默认配置启用,或传入 I18nPluginOptions 自定义。\n */\n i18n?: I18nPluginOptions | true;\n\n /**\n * 微前端 (Garfish)\n *\n * 传入 GarfishPluginOptions 配置。\n */\n garfish?: GarfishPluginOptions;\n\n /**\n * 浏览器兼容性检查\n *\n * 设为 `true` 使用默认配置启用,或传入 BrowserCheckPluginOptions 自定义。\n */\n browserCheck?: BrowserCheckPluginOptions | true;\n\n /**\n * Biome 代码规范\n *\n * 设为 `true` 使用默认配置启用,或传入 BiomePluginOptions 自定义。\n */\n biome?: BiomePluginOptions | true;\n\n /**\n * Mock 数据服务\n *\n * 设为 `true` 使用默认配置启用,或传入 MockPluginOptions 自定义。\n */\n mock?: MockPluginOptions | true;\n\n /**\n * 构建分析\n *\n * 设为 `true` 使用默认配置启用,或传入 AnalyticsPluginOptions 自定义。\n */\n analytics?: AnalyticsPluginOptions | true;\n}\n\n// ---------------------------------------------------------------------------\n// 主配置\n// ---------------------------------------------------------------------------\n\n/**\n * 框架内部配置(不含插件快捷键)\n *\n * 内部模块使用此类型,通过 `Required<YwkfConfig>` 确保所有字段有值。\n */\nexport interface YwkfConfig {\n /** 应用名称 */\n appName?: string;\n /** 应用中文名 */\n appCName?: string;\n /** 开发服务器配置 */\n dev?: DevServerConfig;\n /** 输出配置 */\n output?: OutputConfig;\n /** HTML 配置 */\n html?: HtmlConfig;\n /** 样式配置 */\n style?: StyleConfig;\n /** 路由配置 */\n router?: RouterConfig;\n /** 微前端配置 */\n microFrontend?: MicroFrontendConfig;\n /** 性能配置 */\n performance?: PerformanceConfig;\n /** 工具链配置 */\n tools?: ToolsConfig;\n /** 环境变量配置 */\n env?: EnvConfig;\n /** 路径别名 */\n alias?: Record<string, string>;\n /** 插件列表 */\n plugins?: PluginConfig[];\n}\n\n/**\n * 用户输入配置(支持插件快捷键)\n *\n * 支持两种插件声明方式(可混用):\n *\n * **方式一:快捷配置(推荐)**\n * ```ts\n * defineConfig({\n * appName: \"my-app\",\n * theme: { darkMode: true },\n * browserCheck: { fromBrowserslist: true },\n * })\n * ```\n *\n * **方式二:手动插件(完全控制)**\n * ```ts\n * import { themePlugin, browserCheckPlugin } from \"@4399ywkf/core\";\n * defineConfig({\n * plugins: [themePlugin({ darkMode: true }), browserCheckPlugin()],\n * })\n * ```\n *\n * 两种方式可以混合使用。快捷配置中的插件与 `plugins` 数组合并时,\n * 同名插件以 `plugins` 数组中的为准(显式声明优先)。\n */\nexport interface YwkfUserConfig extends YwkfConfig, BuiltinPluginConfig, OptionalPluginConfig {}\n\n/**\n * 定义配置的辅助函数(提供类型提示)\n *\n * 接受 `YwkfUserConfig`(含插件快捷键),返回 `YwkfConfig`(内部类型)。\n * 类型转换在运行时由 `normalizeConfig` 完成。\n */\nexport function defineConfig(config: YwkfUserConfig): YwkfConfig {\n return config as YwkfConfig;\n}\n\n/**\n * 默认配置\n */\nexport const defaultConfig: Required<YwkfConfig> = {\n appName: \"app\",\n appCName: \"应用\",\n dev: {\n port: 3000,\n host: \"localhost\",\n proxy: {},\n https: false,\n },\n output: {\n path: \"dist\",\n publicPath: \"/\",\n clean: true,\n },\n html: {\n title: \"应用\",\n template: \"public/index.html\",\n favicon: \"public/favicon.ico\",\n mountRoot: \"root\",\n },\n style: {\n cssModules: true,\n less: { enabled: true, lessOptions: { javascriptEnabled: true } },\n sass: { enabled: true, sassOptions: {} },\n tailwindcss: true,\n },\n router: {\n basename: \"/\",\n conventional: false,\n pagesDir: \"src/pages\",\n exclude: [\n /\\/components?\\//,\n /\\/models\\//,\n /\\/utils?\\//,\n /^_/,\n /\\.d\\.ts$/,\n /\\.(test|spec|e2e)\\.(ts|tsx|js|jsx)$/,\n ],\n },\n microFrontend: {\n enabled: false,\n name: \"app\",\n framework: \"qiankun\",\n },\n performance: {\n rsdoctor: false,\n splitChunks: true,\n dropConsole: false,\n },\n tools: {},\n env: {\n publicEnvFile: \"config/env/.env.public\",\n envDir: \"config/env\",\n },\n alias: {},\n plugins: [],\n};\n"],"mappings":"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","names":["existsSync","resolve","existsSync","join","join","existsSync","existsSync","writeFileSync","join","join","existsSync","writeFileSync","existsSync","join","existsSync","join","resolve","existsSync","writeFileSync","join","join","existsSync","writeFileSync","join","join","existsSync","mkdirSync","writeFileSync","join","join","existsSync","resolve","mkdirSync","writeFileSync","resolve","existsSync"]}
|