@chenhui996/gg-cli 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/index.js +15 -0
  2. package/dist/index.js.map +1 -1
  3. package/dist/template/operations-tem/.env +1 -0
  4. package/dist/template/operations-tem/README.md +146 -0
  5. package/dist/template/operations-tem/eslint.config.js +27 -0
  6. package/dist/template/operations-tem/package-lock.json +4672 -0
  7. package/dist/template/{react-temp2 → operations-tem}/package.json +11 -2
  8. package/dist/template/operations-tem/src/api/user.ts +21 -0
  9. package/dist/template/operations-tem/src/assets/Frame 20.png +0 -0
  10. package/dist/template/operations-tem/src/components/Chart/index.tsx +22 -0
  11. package/dist/template/operations-tem/src/layouts/BasicLayout.tsx +183 -0
  12. package/dist/template/operations-tem/src/main.tsx +38 -0
  13. package/dist/template/operations-tem/src/pages/404.tsx +32 -0
  14. package/dist/template/operations-tem/src/pages/about/index.tsx +8 -0
  15. package/dist/template/operations-tem/src/pages/calendar/index.tsx +8 -0
  16. package/dist/template/operations-tem/src/pages/dashboard/index.tsx +72 -0
  17. package/dist/template/operations-tem/src/pages/home/index.less +59 -0
  18. package/dist/template/operations-tem/src/pages/home/index.tsx +188 -0
  19. package/dist/template/operations-tem/src/pages/settings/index.tsx +8 -0
  20. package/dist/template/operations-tem/src/pages/workspace/index.tsx +8 -0
  21. package/dist/template/operations-tem/src/router/index.tsx +75 -0
  22. package/dist/template/operations-tem/src/store/useCounterStore.ts +24 -0
  23. package/dist/template/operations-tem/src/style.less +3 -0
  24. package/dist/template/operations-tem/src/utils/request/index.ts +108 -0
  25. package/dist/template/{react-temp2 → operations-tem}/vite.config.ts +7 -0
  26. package/dist/template/{react-temp2 → react19}/index.html +1 -1
  27. package/dist/template/{react-temp1 → react19}/src/main.tsx +1 -1
  28. package/package.json +2 -2
  29. package/dist/template/react-temp2/README.md +0 -75
  30. package/dist/template/react-temp2/eslint.config.js +0 -23
  31. package/dist/template/react-temp2/src/App.css +0 -184
  32. package/dist/template/react-temp2/src/App.tsx +0 -121
  33. package/dist/template/react-temp2/src/assets/hero.png +0 -0
  34. package/dist/template/react-temp2/src/assets/vite.svg +0 -1
  35. package/dist/template/react-temp2/src/index.css +0 -111
  36. package/dist/template/react-temp2/src/main.tsx +0 -10
  37. /package/dist/template/{react-temp1 → operations-tem}/index.html +0 -0
  38. /package/dist/template/{react-temp1 → operations-tem}/public/favicon.svg +0 -0
  39. /package/dist/template/{react-temp1 → operations-tem}/public/icons.svg +0 -0
  40. /package/dist/template/{react-temp1 → operations-tem}/src/assets/react.svg +0 -0
  41. /package/dist/template/{react-temp1 → operations-tem}/tsconfig.app.json +0 -0
  42. /package/dist/template/{react-temp1 → operations-tem}/tsconfig.json +0 -0
  43. /package/dist/template/{react-temp1 → operations-tem}/tsconfig.node.json +0 -0
  44. /package/dist/template/{react-temp1 → react19}/README.md +0 -0
  45. /package/dist/template/{react-temp1 → react19}/eslint.config.js +0 -0
  46. /package/dist/template/{react-temp1 → react19}/package.json +0 -0
  47. /package/dist/template/{react-temp2 → react19}/public/favicon.svg +0 -0
  48. /package/dist/template/{react-temp2 → react19}/public/icons.svg +0 -0
  49. /package/dist/template/{react-temp1 → react19}/src/App.css +0 -0
  50. /package/dist/template/{react-temp1 → react19}/src/App.tsx +0 -0
  51. /package/dist/template/{react-temp1 → react19}/src/assets/hero.png +0 -0
  52. /package/dist/template/{react-temp2 → react19}/src/assets/react.svg +0 -0
  53. /package/dist/template/{react-temp1 → react19}/src/assets/vite.svg +0 -0
  54. /package/dist/template/{react-temp1 → react19}/src/index.css +0 -0
  55. /package/dist/template/{react-temp2 → react19}/tsconfig.app.json +0 -0
  56. /package/dist/template/{react-temp2 → react19}/tsconfig.json +0 -0
  57. /package/dist/template/{react-temp2 → react19}/tsconfig.node.json +0 -0
  58. /package/dist/template/{react-temp1 → react19}/vite.config.ts +0 -0
package/dist/index.js CHANGED
@@ -129,7 +129,22 @@ async function create(projectName) {
129
129
  }
130
130
  }
131
131
 
132
+ // src/pre/index.ts
133
+ import chalk2 from "chalk";
134
+ function checkNodeVersion() {
135
+ const currentVersion = process.version;
136
+ const version = currentVersion.replace(/^v/, "");
137
+ const [major] = version.split(".").map(Number);
138
+ if (major < 22) {
139
+ console.error(chalk2.red(`
140
+ \u274C \u9519\u8BEF\uFF1A\u5F53\u524D Node.js \u7248\u672C (${currentVersion}) \u8FC7\u4F4E\uFF01`));
141
+ console.error(chalk2.yellow("\u26A0\uFE0F \u8BF7\u5347\u7EA7 Node.js \u7248\u672C\uFF0C\u4E0D\u4F4E\u4E8E v22.19.0"));
142
+ process.exit(1);
143
+ }
144
+ }
145
+
132
146
  // src/index.ts
147
+ checkNodeVersion();
133
148
  var program = new Command();
134
149
  program.name("gg-cli").description("\u524D\u7AEF\u811A\u624B\u67B6\u5DE5\u5177").version("1.0.0");
135
150
  program.command("create [project-name]", { isDefault: true }).description("\u521B\u5EFA\u4E00\u4E2A\u65B0\u9879\u76EE").action((projectName) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/utils/pkg-manager.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { create } from './commands/create.js';\n\nconst program = new Command();\n\nprogram\n .name('gg-cli')\n .description('前端脚手架工具')\n .version('1.0.0');\n\n// 将 create 设为默认命令,参数改为可选 [project-name]\nprogram\n .command('create [project-name]', { isDefault: true })\n .description('创建一个新项目')\n .action((projectName) => {\n create(projectName);\n });\n\nprogram.parse(process.argv);\n","import { input, select, confirm } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { execa } from 'execa';\nimport ora from 'ora';\nimport { getUserPkgManager } from '../utils/pkg-manager.js';\n\nexport async function create(projectName?: string) {\n // 获取包管理器\n const pkgManager = getUserPkgManager();\n\n // 获取当前文件路径 (dist/index.js)\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n \n // 模板目录路径 (假设模板被复制到了 dist/template)\n const templateDir = path.resolve(__dirname, 'template');\n \n // 检查模板目录是否存在\n if (!fs.existsSync(templateDir)) {\n console.error(chalk.red('❌ 错误:未找到模板目录!'));\n console.log(chalk.yellow(`预期路径: ${templateDir}`));\n process.exit(1);\n }\n\n // 获取所有可用模板\n const templates = fs.readdirSync(templateDir).filter(file => {\n return fs.statSync(path.join(templateDir, file)).isDirectory();\n });\n\n if (templates.length === 0) {\n console.error(chalk.red('❌ 错误:模板目录为空!'));\n process.exit(1);\n }\n\n try {\n // 1. 如果没有传入项目名称,则询问\n let finalProjectName = projectName;\n if (!finalProjectName) {\n finalProjectName = await input({\n message: '请输入项目名称:',\n validate: (value) => {\n if (!value.trim()) return '项目名称不能为空';\n return true;\n }\n });\n }\n\n // 2. 选择模板\n const template = await select({\n message: '请选择项目模板:',\n choices: templates.map(t => ({\n name: t,\n value: t,\n })),\n });\n\n // 3. 是否安装依赖\n const install = await confirm({\n message: '是否自动安装依赖?',\n default: true,\n });\n\n console.log(chalk.blue(`\\n🚀 准备创建项目: ${finalProjectName}`));\n\n const selectedTemplatePath = path.join(templateDir, template);\n const targetPath = path.resolve(process.cwd(), finalProjectName!);\n\n // 检查目标目录是否已存在\n if (fs.existsSync(targetPath)) {\n const overwrite = await confirm({\n message: `目录 ${finalProjectName} 已存在,是否覆盖?`,\n default: false\n });\n\n if (!overwrite) {\n console.log(chalk.yellow('已取消创建。'));\n return;\n }\n await fs.remove(targetPath);\n }\n\n const spinner = ora('正在复制模板...').start();\n await fs.copy(selectedTemplatePath, targetPath);\n \n // 修改 package.json 中的 name\n const pkgPath = path.join(targetPath, 'package.json');\n if (await fs.pathExists(pkgPath)) {\n const pkg = await fs.readJson(pkgPath);\n pkg.name = finalProjectName;\n await fs.writeJson(pkgPath, pkg, { spaces: 2 });\n }\n spinner.succeed('模板复制完成');\n\n if (install) {\n const installSpinner = ora(`正在安装依赖 (${pkgManager} install)...`).start();\n try {\n await execa(pkgManager, ['install'], { cwd: targetPath });\n installSpinner.succeed('依赖安装成功');\n } catch (error) {\n installSpinner.fail('依赖安装失败');\n console.error(chalk.red(error));\n }\n }\n\n // 4. 初始化 git 仓库\n const gitSpinner = ora('正在初始化 Git 仓库...').start();\n try {\n // 先检查是否已经存在 .git 目录(防止覆盖模板自带的 git,虽然按理说模板不该带 .git)\n if (fs.existsSync(path.join(targetPath, '.git'))) {\n gitSpinner.succeed('Git 仓库已存在,跳过初始化');\n } else {\n await execa('git', ['init'], { cwd: targetPath });\n gitSpinner.succeed('Git 仓库初始化成功');\n }\n } catch (error) {\n gitSpinner.warn('Git 仓库初始化失败 (可能是未安装 git)');\n }\n\n console.log(chalk.green(`\\n✅ 项目 ${finalProjectName} 创建成功!`));\n console.log(`\\n接下来你可以:\\n`);\n console.log(chalk.cyan(` cd ${finalProjectName}`));\n if (!install) {\n console.log(chalk.cyan(` ${pkgManager} install`));\n }\n console.log(chalk.cyan(` ${pkgManager === 'npm' ? 'npm run' : pkgManager} dev`));\n\n } catch (err) {\n if (err instanceof Error && err.message.includes('User force closed')) {\n console.log(chalk.yellow('\\n用户取消操作'));\n process.exit(0);\n }\n console.error(chalk.red('❌ 创建项目失败:'), err);\n }\n}\n","export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';\n\nexport function getUserPkgManager(): PackageManager {\n // 从环境变量中获取用户使用的包管理器信息\n const userAgent = process.env.npm_config_user_agent;\n\n if (userAgent) {\n if (userAgent.startsWith('yarn')) {\n return 'yarn';\n } else if (userAgent.startsWith('pnpm')) {\n return 'pnpm';\n } else if (userAgent.startsWith('bun')) {\n return 'bun';\n }\n }\n\n return 'npm';\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/create.ts","../src/utils/pkg-manager.ts","../src/pre/index.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { create } from './commands/create.js';\nimport { checkNodeVersion } from './pre/index.js';\n\n// 1. 前置检查:Node.js 版本\ncheckNodeVersion();\n\nconst program = new Command();\n\nprogram\n .name('gg-cli')\n .description('前端脚手架工具')\n .version('1.0.0');\n\n// 将 create 设为默认命令,参数改为可选 [project-name]\nprogram\n .command('create [project-name]', { isDefault: true })\n .description('创建一个新项目')\n .action((projectName) => {\n create(projectName);\n });\n\nprogram.parse(process.argv);\n","import { input, select, confirm } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { execa } from 'execa';\nimport ora from 'ora';\nimport { getUserPkgManager } from '../utils/pkg-manager.js';\n\nexport async function create(projectName?: string) {\n // 获取包管理器\n const pkgManager = getUserPkgManager();\n\n // 获取当前文件路径 (dist/index.js)\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n \n // 模板目录路径 (假设模板被复制到了 dist/template)\n const templateDir = path.resolve(__dirname, 'template');\n \n // 检查模板目录是否存在\n if (!fs.existsSync(templateDir)) {\n console.error(chalk.red('❌ 错误:未找到模板目录!'));\n console.log(chalk.yellow(`预期路径: ${templateDir}`));\n process.exit(1);\n }\n\n // 获取所有可用模板\n const templates = fs.readdirSync(templateDir).filter(file => {\n return fs.statSync(path.join(templateDir, file)).isDirectory();\n });\n\n if (templates.length === 0) {\n console.error(chalk.red('❌ 错误:模板目录为空!'));\n process.exit(1);\n }\n\n try {\n // 1. 如果没有传入项目名称,则询问\n let finalProjectName = projectName;\n if (!finalProjectName) {\n finalProjectName = await input({\n message: '请输入项目名称:',\n validate: (value) => {\n if (!value.trim()) return '项目名称不能为空';\n return true;\n }\n });\n }\n\n // 2. 选择模板\n const template = await select({\n message: '请选择项目模板:',\n choices: templates.map(t => ({\n name: t,\n value: t,\n })),\n });\n\n // 3. 是否安装依赖\n const install = await confirm({\n message: '是否自动安装依赖?',\n default: true,\n });\n\n console.log(chalk.blue(`\\n🚀 准备创建项目: ${finalProjectName}`));\n\n const selectedTemplatePath = path.join(templateDir, template);\n const targetPath = path.resolve(process.cwd(), finalProjectName!);\n\n // 检查目标目录是否已存在\n if (fs.existsSync(targetPath)) {\n const overwrite = await confirm({\n message: `目录 ${finalProjectName} 已存在,是否覆盖?`,\n default: false\n });\n\n if (!overwrite) {\n console.log(chalk.yellow('已取消创建。'));\n return;\n }\n await fs.remove(targetPath);\n }\n\n const spinner = ora('正在复制模板...').start();\n await fs.copy(selectedTemplatePath, targetPath);\n \n // 修改 package.json 中的 name\n const pkgPath = path.join(targetPath, 'package.json');\n if (await fs.pathExists(pkgPath)) {\n const pkg = await fs.readJson(pkgPath);\n pkg.name = finalProjectName;\n await fs.writeJson(pkgPath, pkg, { spaces: 2 });\n }\n spinner.succeed('模板复制完成');\n\n if (install) {\n const installSpinner = ora(`正在安装依赖 (${pkgManager} install)...`).start();\n try {\n await execa(pkgManager, ['install'], { cwd: targetPath });\n installSpinner.succeed('依赖安装成功');\n } catch (error) {\n installSpinner.fail('依赖安装失败');\n console.error(chalk.red(error));\n }\n }\n\n // 4. 初始化 git 仓库\n const gitSpinner = ora('正在初始化 Git 仓库...').start();\n try {\n // 先检查是否已经存在 .git 目录(防止覆盖模板自带的 git,虽然按理说模板不该带 .git)\n if (fs.existsSync(path.join(targetPath, '.git'))) {\n gitSpinner.succeed('Git 仓库已存在,跳过初始化');\n } else {\n await execa('git', ['init'], { cwd: targetPath });\n gitSpinner.succeed('Git 仓库初始化成功');\n }\n } catch (error) {\n gitSpinner.warn('Git 仓库初始化失败 (可能是未安装 git)');\n }\n\n console.log(chalk.green(`\\n✅ 项目 ${finalProjectName} 创建成功!`));\n console.log(`\\n接下来你可以:\\n`);\n console.log(chalk.cyan(` cd ${finalProjectName}`));\n if (!install) {\n console.log(chalk.cyan(` ${pkgManager} install`));\n }\n console.log(chalk.cyan(` ${pkgManager === 'npm' ? 'npm run' : pkgManager} dev`));\n\n } catch (err) {\n if (err instanceof Error && err.message.includes('User force closed')) {\n console.log(chalk.yellow('\\n用户取消操作'));\n process.exit(0);\n }\n console.error(chalk.red('❌ 创建项目失败:'), err);\n }\n}\n","export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';\n\nexport function getUserPkgManager(): PackageManager {\n // 从环境变量中获取用户使用的包管理器信息\n const userAgent = process.env.npm_config_user_agent;\n\n if (userAgent) {\n if (userAgent.startsWith('yarn')) {\n return 'yarn';\n } else if (userAgent.startsWith('pnpm')) {\n return 'pnpm';\n } else if (userAgent.startsWith('bun')) {\n return 'bun';\n }\n }\n\n return 'npm';\n}\n","import chalk from 'chalk';\n\n/**\n * 检查当前 Node.js 版本是否符合要求\n * 要求 Node.js 版本 >= 22.19.0\n */\nexport function checkNodeVersion() {\n const currentVersion = process.version;\n // 去掉版本号前的 'v',例如 'v22.5.1' -> '22.5.1'\n const version = currentVersion.replace(/^v/, '');\n const [major] = version.split('.').map(Number);\n\n if (major < 22) {\n console.error(chalk.red(`\\n❌ 错误:当前 Node.js 版本 (${currentVersion}) 过低!`));\n console.error(chalk.yellow('⚠️ 请升级 Node.js 版本,不低于 v22.19.0'));\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["chalk"]}
@@ -0,0 +1 @@
1
+ VITE_API_BASE_URL=/api
@@ -0,0 +1,146 @@
1
+ # Operations Template (运营后台模版)
2
+
3
+ 基于 React 19 + TypeScript + Vite 8 + Ant Design 6 的现代化后台管理系统模版。
4
+ 本模版专为快速构建企业级中后台应用而设计,集成了最佳实践的工程化配置、清晰的架构分层和美观的 UI 设计。
5
+
6
+ ## ✨ 特性
7
+
8
+ - **最新技术栈**: 采用 React 19、Vite 8、TypeScript 5 等前沿技术。
9
+ - **UI 设计**: 集成 Ant Design 6,配合 Less 预处理器,深度还原 Figma 设计稿风格。
10
+ - **函数式编程**: 全面采用 React Hooks 和函数式组件,代码简洁、易维护。
11
+ - **状态管理**: 使用 Zustand 5 进行轻量级全局状态管理。
12
+ - **路由管理**: 基于 React Router 7.x 的 Data API 路由模式。
13
+ - **网络请求**: 封装 Axios 1.x,统一处理拦截器、错误码和 TypeScript 类型定义。
14
+ - **工程化**: 配置 ESLint 9、Prettier 规范代码风格。
15
+
16
+ ## 📦 目录结构
17
+
18
+ ```bash
19
+ src/
20
+ ├── api/ # API 接口定义层
21
+ │ └── user.ts # 用户相关接口示例
22
+ ├── assets/ # 静态资源文件 (图片、图标等)
23
+ ├── components/ # 公共组件库
24
+ │ └── Chart/ # ECharts 图表组件封装
25
+ ├── layouts/ # 布局组件
26
+ │ └── BasicLayout.tsx # 基础布局 (侧边栏 + 顶栏 + 内容区)
27
+ ├── pages/ # 页面组件 (路由视图)
28
+ │ ├── home/ # 首页 (包含欢迎语、搜索、快捷功能、任务列表)
29
+ │ ├── dashboard/ # 数据看板 (ECharts 示例)
30
+ │ └── about/ # 关于页面
31
+ ├── router/ # 路由配置
32
+ │ └── index.tsx # 路由表定义
33
+ ├── store/ # 全局状态管理 (Zustand)
34
+ │ └── useCounterStore.ts
35
+ ├── utils/ # 工具函数
36
+ │ └── request/ # Axios 二次封装
37
+ ├── main.tsx # 应用入口
38
+ ├── App.tsx # 根组件
39
+ └── vite-env.d.ts # Vite 环境变量类型声明
40
+ ```
41
+
42
+ ## 🚀 快速上手
43
+
44
+ ### 1. 环境准备
45
+
46
+ 确保您的本地环境已安装 Node.js (推荐 v18+)。
47
+
48
+ ### 2. 安装依赖
49
+
50
+ ```bash
51
+ npm install
52
+ # 或者
53
+ yarn
54
+ # 或者
55
+ pnpm install
56
+ ```
57
+
58
+ ### 3. 启动开发服务器
59
+
60
+ ```bash
61
+ npm run dev
62
+ ```
63
+
64
+ 浏览器访问 `http://localhost:5173` 即可看到效果。
65
+
66
+ ### 4. 构建生产环境
67
+
68
+ ```bash
69
+ npm run build
70
+ ```
71
+
72
+ ## 🛠 开发指南
73
+
74
+ ### 1. 新增页面
75
+
76
+ 1. 在 `src/pages` 下新建文件夹,例如 `src/pages/product`。
77
+ 2. 创建 `index.tsx` 并导出默认组件。
78
+ 3. 在 `src/router/index.tsx` 中配置路由规则。
79
+
80
+ ### 2. 样式开发
81
+
82
+ 项目支持 **Less** 预处理器。
83
+ - **全局样式**: 修改 `src/index.css` 或配置 `src/main.tsx` 中的 Ant Design Token。
84
+ - **组件样式**: 推荐使用 `.less` 文件,并在组件中引入。
85
+ ```less
86
+ // src/pages/home/index.less
87
+ .home-page {
88
+ padding: 20px;
89
+ }
90
+ ```
91
+
92
+ ### 3. 网络请求
93
+
94
+ 使用 `src/utils/request` 中导出的 `request` 实例。
95
+
96
+ ```typescript
97
+ import { request } from '@/utils/request';
98
+
99
+ // 定义响应类型
100
+ interface UserInfo {
101
+ id: number;
102
+ name: string;
103
+ }
104
+
105
+ // 发起请求
106
+ const getUser = () => {
107
+ return request.get<UserInfo>('/api/user/1');
108
+ };
109
+ ```
110
+
111
+ ### 4. 状态管理 (Zustand)
112
+
113
+ ```typescript
114
+ import { create } from 'zustand';
115
+
116
+ interface UserState {
117
+ name: string;
118
+ setName: (name: string) => void;
119
+ }
120
+
121
+ export const useUserStore = create<UserState>((set) => ({
122
+ name: 'Guest',
123
+ setName: (name) => set({ name }),
124
+ }));
125
+
126
+ // 在组件中使用
127
+ const { name, setName } = useUserStore();
128
+ ```
129
+
130
+ ## 🎨 设计规范
131
+
132
+ - **主色调**: `#4F46E5` (Indigo)
133
+ - **圆角**: 全局组件圆角 `8px`,卡片圆角 `12px`
134
+ - **布局**: 左侧固定侧边栏 (`240px`) + 顶部通栏
135
+ - **图标**: 使用 `@ant-design/icons`
136
+
137
+ ## 🤝 贡献指南
138
+
139
+ 1. Fork 本仓库
140
+ 2. 新建 feature 分支
141
+ 3. 提交代码并 Push
142
+ 4. 发起 Pull Request
143
+
144
+ ---
145
+
146
+ © 2024 Operations Template. All Rights Reserved.
@@ -0,0 +1,27 @@
1
+ import js from "@eslint/js";
2
+ import globals from "globals";
3
+ import reactHooks from "eslint-plugin-react-hooks";
4
+ import reactRefresh from "eslint-plugin-react-refresh";
5
+ import tseslint from "typescript-eslint";
6
+ import { defineConfig, globalIgnores } from "eslint/config";
7
+
8
+ export default defineConfig([
9
+ globalIgnores(["dist"]),
10
+ {
11
+ files: ["**/*.{ts,tsx}"],
12
+ extends: [
13
+ js.configs.recommended,
14
+ tseslint.configs.recommended,
15
+ reactHooks.configs.flat.recommended,
16
+ reactRefresh.configs.vite,
17
+ ],
18
+ languageOptions: {
19
+ ecmaVersion: 2020,
20
+ globals: globals.browser,
21
+ },
22
+ rules: {
23
+ "@typescript-eslint/no-explicit-any": "off",
24
+ "react-refresh/only-export-components": "off",
25
+ },
26
+ },
27
+ ]);