@qlover/create-app 0.7.5 → 0.7.7
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/CHANGELOG.md +257 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/next-app/.env.template +22 -0
- package/dist/templates/next-app/.prettierignore +58 -0
- package/dist/templates/next-app/README.md +36 -0
- package/dist/templates/next-app/build/generateLocales.ts +25 -0
- package/dist/templates/next-app/config/IOCIdentifier.ts +45 -0
- package/dist/templates/next-app/config/Identifier/common.error.ts +34 -0
- package/dist/templates/next-app/config/Identifier/common.ts +62 -0
- package/dist/templates/next-app/config/Identifier/index.ts +10 -0
- package/dist/templates/next-app/config/Identifier/page.about.ts +181 -0
- package/dist/templates/next-app/config/Identifier/page.executor.ts +272 -0
- package/dist/templates/next-app/config/Identifier/page.home.ts +63 -0
- package/dist/templates/next-app/config/Identifier/page.identifiter.ts +39 -0
- package/dist/templates/next-app/config/Identifier/page.jsonStorage.ts +72 -0
- package/dist/templates/next-app/config/Identifier/page.login.ts +165 -0
- package/dist/templates/next-app/config/Identifier/page.register.ts +147 -0
- package/dist/templates/next-app/config/Identifier/page.request.ts +182 -0
- package/dist/templates/next-app/config/common.ts +34 -0
- package/dist/templates/next-app/config/i18n/PageI18nInterface.ts +51 -0
- package/dist/templates/next-app/config/i18n/i18nConfig.ts +12 -0
- package/dist/templates/next-app/config/i18n/index.ts +3 -0
- package/dist/templates/next-app/config/i18n/loginI18n.ts +42 -0
- package/dist/templates/next-app/config/theme.ts +23 -0
- package/dist/templates/next-app/docs/env.md +94 -0
- package/dist/templates/next-app/eslint.config.mjs +181 -0
- package/dist/templates/next-app/next.config.ts +21 -0
- package/dist/templates/next-app/package.json +58 -0
- package/dist/templates/next-app/plugins/eslint-plugin-testid.mjs +94 -0
- package/dist/templates/next-app/plugins/generateLocalesPlugin.ts +33 -0
- package/dist/templates/next-app/postcss.config.mjs +5 -0
- package/dist/templates/next-app/public/file.svg +1 -0
- package/dist/templates/next-app/public/globe.svg +1 -0
- package/dist/templates/next-app/public/locales/en/common.json +183 -0
- package/dist/templates/next-app/public/locales/zh/common.json +183 -0
- package/dist/templates/next-app/public/next.svg +1 -0
- package/dist/templates/next-app/public/vercel.svg +1 -0
- package/dist/templates/next-app/public/window.svg +1 -0
- package/dist/templates/next-app/src/app/[locale]/favicon.ico +0 -0
- package/dist/templates/next-app/src/app/[locale]/layout.tsx +44 -0
- package/dist/templates/next-app/src/app/[locale]/login/FeatureItem.tsx +13 -0
- package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +115 -0
- package/dist/templates/next-app/src/app/[locale]/login/page.tsx +73 -0
- package/dist/templates/next-app/src/app/[locale]/not-found.tsx +24 -0
- package/dist/templates/next-app/src/app/[locale]/page.tsx +106 -0
- package/dist/templates/next-app/src/base/cases/AppConfig.ts +15 -0
- package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +33 -0
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +25 -0
- package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +11 -0
- package/dist/templates/next-app/src/base/services/I18nService.ts +115 -0
- package/dist/templates/next-app/src/base/services/UserService.ts +23 -0
- package/dist/templates/next-app/src/core/IOC.ts +58 -0
- package/dist/templates/next-app/src/core/IocRegisterImpl.ts +100 -0
- package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +98 -0
- package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +47 -0
- package/dist/templates/next-app/src/core/bootstraps/IocIdentifierTest.ts +26 -0
- package/dist/templates/next-app/src/core/bootstraps/PrintBootstrap.ts +18 -0
- package/dist/templates/next-app/src/core/globals.ts +21 -0
- package/dist/templates/next-app/src/i18n/request.ts +22 -0
- package/dist/templates/next-app/src/i18n/routing.ts +30 -0
- package/dist/templates/next-app/src/middleware.ts +22 -0
- package/dist/templates/next-app/src/server/getServerI18n.ts +26 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/_default.css +239 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/dark.css +178 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/index.css +3 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/no-context.css +34 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/pink.css +204 -0
- package/dist/templates/next-app/src/styles/css/index.css +6 -0
- package/dist/templates/next-app/src/styles/css/page.css +19 -0
- package/dist/templates/next-app/src/styles/css/tailwind.css +5 -0
- package/dist/templates/next-app/src/styles/css/themes/_default.css +29 -0
- package/dist/templates/next-app/src/styles/css/themes/dark.css +29 -0
- package/dist/templates/next-app/src/styles/css/themes/index.css +3 -0
- package/dist/templates/next-app/src/styles/css/themes/pink.css +29 -0
- package/dist/templates/next-app/src/styles/css/zIndex.css +9 -0
- package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +42 -0
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +25 -0
- package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +45 -0
- package/dist/templates/next-app/src/uikit/components/LanguageSwitcher.tsx +52 -0
- package/dist/templates/next-app/src/uikit/components/LocaleLink.tsx +51 -0
- package/dist/templates/next-app/src/uikit/components/NextIntlProvider.tsx +21 -0
- package/dist/templates/next-app/src/uikit/components/ThemeSwitcher.tsx +86 -0
- package/dist/templates/next-app/src/uikit/context/IOCContext.ts +6 -0
- package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +28 -0
- package/dist/templates/next-app/src/uikit/hook/useIOC.ts +37 -0
- package/dist/templates/next-app/src/uikit/hook/useMountedClient.ts +11 -0
- package/dist/templates/next-app/src/uikit/hook/useStore.ts +15 -0
- package/dist/templates/next-app/tailwind.config.ts +8 -0
- package/dist/templates/next-app/tsconfig.json +36 -0
- package/dist/templates/react-app/.env.template +0 -2
- package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +1 -1
- package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +6 -31
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +1 -1
- package/dist/templates/react-app/config/IOCIdentifier.ts +77 -5
- package/dist/templates/react-app/config/app.router.ts +2 -2
- package/dist/templates/react-app/package.json +4 -7
- package/dist/templates/react-app/public/locales/en/common.json +1 -1
- package/dist/templates/react-app/public/locales/zh/common.json +1 -1
- package/dist/templates/react-app/src/App.tsx +9 -4
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +1 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +4 -0
- package/dist/templates/react-app/src/base/cases/DialogHandler.ts +16 -13
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +4 -3
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +2 -2
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +39 -0
- package/dist/templates/react-app/src/base/cases/RequestState.ts +20 -0
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
- package/dist/templates/react-app/src/base/cases/RouterLoader.ts +8 -2
- package/dist/templates/react-app/src/base/port/AsyncStateInterface.ts +7 -0
- package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +24 -0
- package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +10 -0
- package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +20 -0
- package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +20 -0
- package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +23 -0
- package/dist/templates/react-app/src/base/port/RequestStatusInterface.ts +5 -0
- package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +27 -0
- package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +12 -0
- package/dist/templates/react-app/src/base/services/I18nService.ts +10 -6
- package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +23 -5
- package/dist/templates/react-app/src/base/services/RouteService.ts +25 -54
- package/dist/templates/react-app/src/base/services/UserService.ts +10 -20
- package/dist/templates/react-app/src/core/IOC.ts +1 -26
- package/dist/templates/react-app/src/core/IocRegisterImpl.ts +125 -0
- package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +4 -6
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +8 -6
- package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +26 -0
- package/dist/templates/react-app/src/pages/auth/Layout.tsx +2 -2
- package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -6
- package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +8 -7
- package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +8 -19
- package/dist/templates/react-app/src/pages/base/{ErrorIdentifierPage.tsx → IdentifierPage.tsx} +1 -1
- package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +11 -15
- package/dist/templates/react-app/src/pages/base/Layout.tsx +1 -1
- package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +2 -2
- package/dist/templates/react-app/src/pages/base/RequestPage.tsx +34 -46
- package/dist/templates/react-app/src/styles/css/antd-themes/_default.css +2 -2
- package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +2 -2
- package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +2 -2
- package/dist/templates/react-app/src/styles/css/index.css +1 -0
- package/dist/templates/react-app/src/styles/css/page.css +8 -0
- package/dist/templates/react-app/src/styles/css/zIndex.css +9 -0
- package/dist/templates/react-app/src/uikit/{controllers/ExecutorController.ts → bridges/ExecutorPageBridge.ts} +13 -36
- package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +41 -0
- package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +16 -0
- package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +136 -0
- package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +3 -2
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +2 -2
- package/dist/templates/react-app/src/uikit/{providers → components}/ProcessExecutorProvider.tsx +4 -4
- package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +1 -1
- package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +3 -5
- package/dist/templates/react-app/src/uikit/{providers → components}/UserAuthProvider.tsx +3 -3
- package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +5 -2
- package/dist/templates/react-app/src/uikit/hooks/{userRouterService.ts → useNavigateBridge.ts} +3 -3
- package/dist/templates/react-app/src/uikit/hooks/useStore.ts +5 -2
- package/dist/templates/react-app/tsconfig.json +1 -4
- package/package.json +1 -1
- package/dist/templates/react-app/src/base/port/InteractionHubInterface.ts +0 -94
- package/dist/templates/react-app/src/base/port/UIDependenciesInterface.ts +0 -37
- package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +0 -25
- package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +0 -74
- package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +0 -26
- package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +0 -30
- package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +0 -49
- package/dist/templates/react-app/src/uikit/controllers/RequestController.ts +0 -158
- /package/dist/templates/react-app/src/uikit/{providers → components}/BaseRouteProvider.tsx +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# 环境配置指南
|
|
2
|
+
|
|
3
|
+
本项目使用 Next.js 内置的环境变量系统来管理不同环境的配置。
|
|
4
|
+
|
|
5
|
+
## 环境文件
|
|
6
|
+
|
|
7
|
+
项目支持以下环境配置文件:
|
|
8
|
+
|
|
9
|
+
- `.env` - 默认环境配置,适用于所有环境
|
|
10
|
+
- `.env.local` - 本地环境配置,会覆盖 `.env`(不应提交到版本控制)
|
|
11
|
+
- `.env.development` - 开发环境配置
|
|
12
|
+
- `.env.production` - 生产环境配置
|
|
13
|
+
- `.env.test` - 测试环境配置
|
|
14
|
+
|
|
15
|
+
加载优先级(从高到低):
|
|
16
|
+
|
|
17
|
+
1. `.env.local`
|
|
18
|
+
2. `.env.[environment]`
|
|
19
|
+
3. `.env`
|
|
20
|
+
|
|
21
|
+
## 使用方法
|
|
22
|
+
|
|
23
|
+
1. 复制 `.env.template` 创建对应环境的配置文件:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 开发环境
|
|
27
|
+
cp .env.template .env.development
|
|
28
|
+
|
|
29
|
+
# 生产环境
|
|
30
|
+
cp .env.template .env.production
|
|
31
|
+
|
|
32
|
+
# 测试环境
|
|
33
|
+
cp .env.template .env.test
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. 修改对应环境的配置文件内容
|
|
37
|
+
|
|
38
|
+
3. 启动应用时指定环境:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# 开发环境
|
|
42
|
+
APP_ENV=development npm run dev
|
|
43
|
+
|
|
44
|
+
# 生产环境
|
|
45
|
+
APP_ENV=production npm run build
|
|
46
|
+
APP_ENV=production npm run start
|
|
47
|
+
|
|
48
|
+
# 测试环境
|
|
49
|
+
APP_ENV=test npm run test
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 在代码中使用环境变量
|
|
53
|
+
|
|
54
|
+
1. 服务端和客户端都可访问的变量:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// 在 .env 文件中定义
|
|
58
|
+
PUBLIC_API_URL=http://api.example.com
|
|
59
|
+
|
|
60
|
+
// 在代码中使用
|
|
61
|
+
console.log(process.env.PUBLIC_API_URL)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
2. 仅服务端可访问的变量:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// 在 .env 文件中定义(以 PRIVATE_ 开头)
|
|
68
|
+
PRIVATE_API_KEY = secret_key;
|
|
69
|
+
|
|
70
|
+
// 在服务端代码中使用
|
|
71
|
+
console.log(process.env.PRIVATE_API_KEY);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
3. 使用运行时配置:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import getConfig from 'next/config';
|
|
78
|
+
|
|
79
|
+
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();
|
|
80
|
+
|
|
81
|
+
// 服务端配置
|
|
82
|
+
console.log(serverRuntimeConfig.mySecret);
|
|
83
|
+
|
|
84
|
+
// 公共配置
|
|
85
|
+
console.log(publicRuntimeConfig.appEnv);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 注意事项
|
|
89
|
+
|
|
90
|
+
1. 不要将包含敏感信息的 `.env` 文件提交到版本控制
|
|
91
|
+
2. 确保 `.env.local` 和 `*.env` 文件在 `.gitignore` 中
|
|
92
|
+
3. 使用 `.env.template` 作为配置模板
|
|
93
|
+
4. 环境变量命名推荐使用大写字母和下划线
|
|
94
|
+
5. 在 CI/CD 中使用环境变量时,直接在平台中配置,不要使用 .env 文件
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { dirname } from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { FlatCompat } from '@eslint/eslintrc';
|
|
4
|
+
import importPlugin from 'eslint-plugin-import';
|
|
5
|
+
import prettierPlugin from 'eslint-plugin-prettier';
|
|
6
|
+
import unusedImports from 'eslint-plugin-unused-imports';
|
|
7
|
+
import qloverEslint from '@qlover/eslint-plugin';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
|
|
12
|
+
const compat = new FlatCompat({ baseDirectory: __dirname });
|
|
13
|
+
|
|
14
|
+
const eslintConfig = [
|
|
15
|
+
...compat.extends(
|
|
16
|
+
'next/core-web-vitals',
|
|
17
|
+
'next/typescript',
|
|
18
|
+
'plugin:import/recommended',
|
|
19
|
+
'plugin:import/typescript',
|
|
20
|
+
'plugin:prettier/recommended' // 添加 prettier 推荐配置
|
|
21
|
+
),
|
|
22
|
+
{
|
|
23
|
+
ignores: [
|
|
24
|
+
// dependencies
|
|
25
|
+
'node_modules/**',
|
|
26
|
+
'.pnp/**',
|
|
27
|
+
'.pnp.js',
|
|
28
|
+
|
|
29
|
+
// testing
|
|
30
|
+
'coverage/**',
|
|
31
|
+
'test-results/**',
|
|
32
|
+
|
|
33
|
+
// next.js
|
|
34
|
+
'.next/**',
|
|
35
|
+
'out/**',
|
|
36
|
+
'build/**',
|
|
37
|
+
'dist/**',
|
|
38
|
+
|
|
39
|
+
// misc
|
|
40
|
+
'*.pem',
|
|
41
|
+
|
|
42
|
+
// debug
|
|
43
|
+
'npm-debug.log*',
|
|
44
|
+
'yarn-debug.log*',
|
|
45
|
+
'yarn-error.log*',
|
|
46
|
+
|
|
47
|
+
// env files
|
|
48
|
+
'.env*',
|
|
49
|
+
|
|
50
|
+
// vercel
|
|
51
|
+
'.vercel/**',
|
|
52
|
+
|
|
53
|
+
// typescript
|
|
54
|
+
'*.tsbuildinfo',
|
|
55
|
+
'next-env.d.ts',
|
|
56
|
+
|
|
57
|
+
// cache
|
|
58
|
+
'.cache/**',
|
|
59
|
+
'.eslintcache',
|
|
60
|
+
|
|
61
|
+
// IDE
|
|
62
|
+
'.idea/**',
|
|
63
|
+
'.vscode/**',
|
|
64
|
+
|
|
65
|
+
// package manager
|
|
66
|
+
'package-lock.json',
|
|
67
|
+
'yarn.lock',
|
|
68
|
+
'pnpm-lock.yaml',
|
|
69
|
+
|
|
70
|
+
// config files
|
|
71
|
+
'*.config.js',
|
|
72
|
+
'*.config.mjs',
|
|
73
|
+
'*.config.cjs',
|
|
74
|
+
'postcss.config.*',
|
|
75
|
+
'tailwind.config.*',
|
|
76
|
+
'next.config.*',
|
|
77
|
+
'jest.config.*',
|
|
78
|
+
'babel.config.*',
|
|
79
|
+
|
|
80
|
+
// static assets
|
|
81
|
+
'public/**',
|
|
82
|
+
'**/*.min.js',
|
|
83
|
+
'**/*.bundle.js',
|
|
84
|
+
'**/vendor/**',
|
|
85
|
+
|
|
86
|
+
// generated files
|
|
87
|
+
'coverage/**',
|
|
88
|
+
'.nyc_output/**',
|
|
89
|
+
'storybook-static/**'
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
plugins: {
|
|
94
|
+
'unused-imports': unusedImports,
|
|
95
|
+
import: importPlugin,
|
|
96
|
+
prettier: prettierPlugin,
|
|
97
|
+
'@qlover-eslint': qloverEslint
|
|
98
|
+
},
|
|
99
|
+
rules: {
|
|
100
|
+
'@qlover-eslint/ts-class-method-return': 'error',
|
|
101
|
+
'@qlover-eslint/require-root-testid': 'error',
|
|
102
|
+
// 禁用原始的 no-unused-vars,使用 unused-imports 的规则替代
|
|
103
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
104
|
+
// 强制使用 import type 导入类型
|
|
105
|
+
'@typescript-eslint/consistent-type-imports': [
|
|
106
|
+
'error',
|
|
107
|
+
{
|
|
108
|
+
prefer: 'type-imports',
|
|
109
|
+
disallowTypeAnnotations: true,
|
|
110
|
+
fixStyle: 'separate-type-imports'
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
// 检查未使用的导入
|
|
114
|
+
'unused-imports/no-unused-imports': 'error',
|
|
115
|
+
// 检查未使用的变量,但允许以下划线开头的变量
|
|
116
|
+
'unused-imports/no-unused-vars': [
|
|
117
|
+
'error',
|
|
118
|
+
{
|
|
119
|
+
vars: 'all',
|
|
120
|
+
varsIgnorePattern: '^_',
|
|
121
|
+
args: 'after-used',
|
|
122
|
+
argsIgnorePattern: '^_'
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
// import 语句排序规则
|
|
126
|
+
'import/order': [
|
|
127
|
+
'error',
|
|
128
|
+
{
|
|
129
|
+
groups: [
|
|
130
|
+
'builtin', // Node.js 内置模块
|
|
131
|
+
'external', // 第三方模块
|
|
132
|
+
'internal', // 内部模块(使用 alias 的导入)
|
|
133
|
+
['parent', 'sibling'], // 父级和同级模块
|
|
134
|
+
'index', // 当前目录下的模块
|
|
135
|
+
'object', // 对象导入
|
|
136
|
+
'type' // 类型导入
|
|
137
|
+
],
|
|
138
|
+
pathGroups: [
|
|
139
|
+
{
|
|
140
|
+
pattern: '@/**',
|
|
141
|
+
group: 'internal',
|
|
142
|
+
position: 'after'
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
// "newlines-between": "always", // 不同组之间空一行
|
|
146
|
+
alphabetize: {
|
|
147
|
+
order: 'asc', // 按字母顺序排序
|
|
148
|
+
caseInsensitive: true // 排序时忽略大小写
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
// Prettier 配置
|
|
153
|
+
'prettier/prettier': [
|
|
154
|
+
'error',
|
|
155
|
+
{
|
|
156
|
+
singleQuote: true,
|
|
157
|
+
trailingComma: 'none',
|
|
158
|
+
endOfLine: 'lf'
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
// 默认禁用 export default
|
|
162
|
+
'import/no-default-export': 'error',
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
// 为特定文件允许 default export
|
|
166
|
+
{
|
|
167
|
+
files: [
|
|
168
|
+
'src/app/**/page.tsx',
|
|
169
|
+
'src/app/**/layout.tsx',
|
|
170
|
+
'src/app/**/not-found.tsx',
|
|
171
|
+
'src/i18n/request.ts',
|
|
172
|
+
'src/middleware.ts',
|
|
173
|
+
'**/*.config.*'
|
|
174
|
+
],
|
|
175
|
+
rules: {
|
|
176
|
+
'import/no-default-export': 'off'
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
export default eslintConfig;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import createNextIntlPlugin from 'next-intl/plugin';
|
|
2
|
+
import { generateLocales } from './build/generateLocales';
|
|
3
|
+
import type { NextConfig } from 'next';
|
|
4
|
+
|
|
5
|
+
const withNextIntl = createNextIntlPlugin();
|
|
6
|
+
|
|
7
|
+
// 在构建开始时生成本地化文件
|
|
8
|
+
generateLocales().catch((error) => {
|
|
9
|
+
console.error('Failed to generate locales:', error);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const nextConfig: NextConfig = {
|
|
13
|
+
turbopack: {
|
|
14
|
+
root: __dirname // 明确指定根目录
|
|
15
|
+
},
|
|
16
|
+
env: {
|
|
17
|
+
APP_ENV: process.env.APP_ENV
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default withNextIntl(nextConfig);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "next-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "cross-env APP_ENV=localhost next dev --turbopack",
|
|
7
|
+
"dev:staging": "cross-env APP_ENV=staging next dev --turbopack",
|
|
8
|
+
"dev:prod": "cross-env APP_ENV=production next dev --turbopack",
|
|
9
|
+
"build": "cross-env APP_ENV=localhost next build --turbopack",
|
|
10
|
+
"build:staging": "cross-env APP_ENV=staging next build --turbopack",
|
|
11
|
+
"build:prod": "cross-env APP_ENV=production next build --turbopack",
|
|
12
|
+
"start": "next start",
|
|
13
|
+
"lint": "eslint .",
|
|
14
|
+
"lint:fix": "eslint . --ext .ts,.tsx --fix",
|
|
15
|
+
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
|
|
16
|
+
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
|
|
17
|
+
"fix": "npm run lint:fix && npm run format"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@ant-design/icons": "^6.0.0",
|
|
21
|
+
"@ant-design/nextjs-registry": "^1.1.0",
|
|
22
|
+
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
|
23
|
+
"@brain-toolkit/antd-theme-override": "^0.0.3",
|
|
24
|
+
"@brain-toolkit/bridge": "^0.0.1",
|
|
25
|
+
"@qlover/corekit-bridge": "^1.6.4",
|
|
26
|
+
"@qlover/fe-corekit": "^2.1.0",
|
|
27
|
+
"@qlover/slice-store-react": "^1.4.1",
|
|
28
|
+
"antd": "^5.27.1",
|
|
29
|
+
"clsx": "^2.1.1",
|
|
30
|
+
"inversify": "^7.8.1",
|
|
31
|
+
"lodash": "^4.17.21",
|
|
32
|
+
"next": "15.5.0",
|
|
33
|
+
"next-intl": "^4.3.5",
|
|
34
|
+
"next-themes": "^0.4.6",
|
|
35
|
+
"react": "19.1.0",
|
|
36
|
+
"react-dom": "19.1.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@brain-toolkit/ts2locales": "^0.2.3",
|
|
40
|
+
"@eslint/eslintrc": "^3",
|
|
41
|
+
"@tailwindcss/postcss": "^4",
|
|
42
|
+
"@types/lodash": "^4.17.20",
|
|
43
|
+
"@types/node": "^20",
|
|
44
|
+
"@types/react": "^19",
|
|
45
|
+
"@types/react-dom": "^19",
|
|
46
|
+
"@qlover/eslint-plugin": "file:../../../packages/eslint-plugin",
|
|
47
|
+
"cross-env": "^7.0.3",
|
|
48
|
+
"eslint": "^9",
|
|
49
|
+
"eslint-config-next": "15.5.0",
|
|
50
|
+
"eslint-config-prettier": "^10.1.8",
|
|
51
|
+
"eslint-plugin-import": "^2.32.0",
|
|
52
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
53
|
+
"eslint-plugin-unused-imports": "^4.2.0",
|
|
54
|
+
"prettier": "^3.6.2",
|
|
55
|
+
"tailwindcss": "^4",
|
|
56
|
+
"typescript": "^5"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export const eslintPluginTestId = {
|
|
2
|
+
rules: {
|
|
3
|
+
'require-root-testid': {
|
|
4
|
+
meta: {
|
|
5
|
+
type: 'problem',
|
|
6
|
+
docs: {
|
|
7
|
+
description:
|
|
8
|
+
'Enforce data-testid attribute on root elements of TSX components',
|
|
9
|
+
category: 'Best Practices',
|
|
10
|
+
recommended: true
|
|
11
|
+
},
|
|
12
|
+
fixable: 'code',
|
|
13
|
+
schema: []
|
|
14
|
+
},
|
|
15
|
+
create(context) {
|
|
16
|
+
return {
|
|
17
|
+
JSXElement(node) {
|
|
18
|
+
// 检查是否是组件的根元素
|
|
19
|
+
const isRootElement = (node) => {
|
|
20
|
+
const parent = node.parent;
|
|
21
|
+
if (!parent) return false;
|
|
22
|
+
|
|
23
|
+
// 如果父节点是 return 语句或者是箭头函数的主体,说明这是根元素
|
|
24
|
+
if (
|
|
25
|
+
parent.type === 'ReturnStatement' ||
|
|
26
|
+
(parent.type === 'ArrowFunctionExpression' &&
|
|
27
|
+
parent.body === node)
|
|
28
|
+
) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return false;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (isRootElement(node)) {
|
|
36
|
+
const hasTestId = node.openingElement.attributes.some(
|
|
37
|
+
(attr) =>
|
|
38
|
+
attr.type === 'JSXAttribute' &&
|
|
39
|
+
attr.name.name === 'data-testid'
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (!hasTestId) {
|
|
43
|
+
context.report({
|
|
44
|
+
node: node.openingElement,
|
|
45
|
+
message:
|
|
46
|
+
'Root element of a component must have a data-testid attribute',
|
|
47
|
+
fix(fixer) {
|
|
48
|
+
// 获取组件名称作为 testid 的默认值
|
|
49
|
+
let componentName = '';
|
|
50
|
+
let current = node;
|
|
51
|
+
while (current) {
|
|
52
|
+
if (
|
|
53
|
+
current.type === 'FunctionDeclaration' ||
|
|
54
|
+
current.type === 'VariableDeclarator'
|
|
55
|
+
) {
|
|
56
|
+
componentName = current.id?.name || '';
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
current = current.parent;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const sourceCode = context.getSourceCode();
|
|
63
|
+
const openingElement = node.openingElement;
|
|
64
|
+
const tagToken = sourceCode.getFirstToken(openingElement);
|
|
65
|
+
const hasAttributes = openingElement.attributes.length > 0;
|
|
66
|
+
|
|
67
|
+
if (hasAttributes) {
|
|
68
|
+
// 如果有其他属性,在第一个属性前添加
|
|
69
|
+
const firstAttribute = openingElement.attributes[0];
|
|
70
|
+
const indent = sourceCode
|
|
71
|
+
.getText()
|
|
72
|
+
.slice(0, firstAttribute.range[0])
|
|
73
|
+
.match(/\s*$/)[0];
|
|
74
|
+
return fixer.insertTextBefore(
|
|
75
|
+
firstAttribute,
|
|
76
|
+
`data-testid='${componentName || 'component'}'${indent}`
|
|
77
|
+
);
|
|
78
|
+
} else {
|
|
79
|
+
// 如果没有其他属性,在标签名后面添加
|
|
80
|
+
return fixer.insertTextAfter(
|
|
81
|
+
tagToken,
|
|
82
|
+
` data-testid='${componentName || 'component'}'`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { generateLocales } from '../build/generateLocales';
|
|
2
|
+
import type { NextConfig } from 'next';
|
|
3
|
+
|
|
4
|
+
export function withGenerateLocales(nextConfig: NextConfig = {}) {
|
|
5
|
+
return {
|
|
6
|
+
...nextConfig,
|
|
7
|
+
onDevelopmentStart: async () => {
|
|
8
|
+
try {
|
|
9
|
+
await generateLocales();
|
|
10
|
+
console.log('✅ Locales generated successfully');
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.error('❌ Failed to generate locales:', error);
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
webpack: (config, options) => {
|
|
16
|
+
const { dev, isServer } = options;
|
|
17
|
+
|
|
18
|
+
// 在生产构建开始时生成本地化文件
|
|
19
|
+
if (!dev && isServer) {
|
|
20
|
+
generateLocales().catch((error) => {
|
|
21
|
+
console.error('❌ Failed to generate locales:', error);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 如果原配置有 webpack 配置,则调用它
|
|
26
|
+
if (typeof nextConfig.webpack === 'function') {
|
|
27
|
+
return nextConfig.webpack(config, options);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return config;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|