@qlover/create-app 1.1.0 → 2.0.0
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 +28 -0
- package/dist/index.cjs +9 -9
- package/dist/index.js +9 -9
- package/package.json +3 -2
- package/dist/configs/_common/.editorconfig +0 -23
- package/dist/configs/_common/.env.template +0 -13
- package/dist/configs/_common/.gitattributes +0 -2
- package/dist/configs/_common/.github/workflows/general-check.yml +0 -41
- package/dist/configs/_common/.github/workflows/release.yml +0 -81
- package/dist/configs/_common/.gitignore.template +0 -64
- package/dist/configs/_common/.husky/commit-msg +0 -3
- package/dist/configs/_common/.husky/pre-commit +0 -3
- package/dist/configs/_common/.prettierignore +0 -17
- package/dist/configs/_common/.prettierrc.js +0 -7
- package/dist/configs/_common/.vscode/extensions.json +0 -9
- package/dist/configs/_common/.vscode/react.code-snippets +0 -19
- package/dist/configs/_common/.vscode/settings.json +0 -16
- package/dist/configs/_common/commitlint.config.js +0 -10
- package/dist/configs/_common/package.json.template +0 -75
- package/dist/configs/node-lib/eslint.config.js +0 -50
- package/dist/templates/next-app/.env.template +0 -25
- package/dist/templates/next-app/.prettierignore +0 -58
- package/dist/templates/next-app/README.en.md +0 -130
- package/dist/templates/next-app/README.md +0 -130
- package/dist/templates/next-app/config/IOCIdentifier.ts +0 -74
- package/dist/templates/next-app/config/Identifier/api.ts +0 -41
- package/dist/templates/next-app/config/Identifier/common/admint.table.ts +0 -69
- package/dist/templates/next-app/config/Identifier/common/common.ts +0 -90
- package/dist/templates/next-app/config/Identifier/common/index.ts +0 -3
- package/dist/templates/next-app/config/Identifier/common/validators.ts +0 -34
- package/dist/templates/next-app/config/Identifier/index.ts +0 -3
- package/dist/templates/next-app/config/Identifier/pages/index.ts +0 -7
- package/dist/templates/next-app/config/Identifier/pages/page.about.ts +0 -20
- package/dist/templates/next-app/config/Identifier/pages/page.admin.home.ts +0 -27
- package/dist/templates/next-app/config/Identifier/pages/page.admin.locales.ts +0 -266
- package/dist/templates/next-app/config/Identifier/pages/page.admin.user.ts +0 -293
- package/dist/templates/next-app/config/Identifier/pages/page.home.ts +0 -56
- package/dist/templates/next-app/config/Identifier/pages/page.login.ts +0 -159
- package/dist/templates/next-app/config/Identifier/pages/page.register.ts +0 -177
- package/dist/templates/next-app/config/adminNavs.ts +0 -19
- package/dist/templates/next-app/config/common.ts +0 -43
- package/dist/templates/next-app/config/cookies.ts +0 -23
- package/dist/templates/next-app/config/i18n/AboutI18n.ts +0 -14
- package/dist/templates/next-app/config/i18n/HomeI18n.ts +0 -24
- package/dist/templates/next-app/config/i18n/PageI18nInterface.ts +0 -51
- package/dist/templates/next-app/config/i18n/admin18n.ts +0 -75
- package/dist/templates/next-app/config/i18n/i18nConfig.ts +0 -16
- package/dist/templates/next-app/config/i18n/i18nKeyScheam.ts +0 -36
- package/dist/templates/next-app/config/i18n/index.ts +0 -7
- package/dist/templates/next-app/config/i18n/loginI18n.ts +0 -50
- package/dist/templates/next-app/config/i18n/register18n.ts +0 -44
- package/dist/templates/next-app/config/route.ts +0 -9
- package/dist/templates/next-app/config/theme.ts +0 -28
- package/dist/templates/next-app/docs/en/api.md +0 -387
- package/dist/templates/next-app/docs/en/component.md +0 -544
- package/dist/templates/next-app/docs/en/database.md +0 -496
- package/dist/templates/next-app/docs/en/development-guide.md +0 -727
- package/dist/templates/next-app/docs/en/env.md +0 -563
- package/dist/templates/next-app/docs/en/i18n.md +0 -287
- package/dist/templates/next-app/docs/en/index.md +0 -165
- package/dist/templates/next-app/docs/en/page.md +0 -457
- package/dist/templates/next-app/docs/en/project-structure.md +0 -176
- package/dist/templates/next-app/docs/en/router.md +0 -427
- package/dist/templates/next-app/docs/en/theme.md +0 -532
- package/dist/templates/next-app/docs/en/validator.md +0 -478
- package/dist/templates/next-app/docs/zh/api.md +0 -387
- package/dist/templates/next-app/docs/zh/component.md +0 -544
- package/dist/templates/next-app/docs/zh/database.md +0 -496
- package/dist/templates/next-app/docs/zh/development-guide.md +0 -727
- package/dist/templates/next-app/docs/zh/env.md +0 -563
- package/dist/templates/next-app/docs/zh/i18n.md +0 -287
- package/dist/templates/next-app/docs/zh/index.md +0 -165
- package/dist/templates/next-app/docs/zh/page.md +0 -457
- package/dist/templates/next-app/docs/zh/project-structure.md +0 -176
- package/dist/templates/next-app/docs/zh/router.md +0 -427
- package/dist/templates/next-app/docs/zh/theme.md +0 -532
- package/dist/templates/next-app/docs/zh/validator.md +0 -476
- package/dist/templates/next-app/eslint.config.mjs +0 -285
- package/dist/templates/next-app/make/generateLocales.ts +0 -32
- package/dist/templates/next-app/migrations/schema/LocalesSchema.ts +0 -15
- package/dist/templates/next-app/migrations/schema/UserSchema.ts +0 -38
- package/dist/templates/next-app/migrations/sql/1694244000000.sql +0 -21
- package/dist/templates/next-app/next.config.ts +0 -25
- package/dist/templates/next-app/package.json +0 -87
- package/dist/templates/next-app/postcss.config.mjs +0 -5
- package/dist/templates/next-app/public/favicon.ico +0 -0
- package/dist/templates/next-app/public/file.svg +0 -1
- package/dist/templates/next-app/public/globe.svg +0 -1
- package/dist/templates/next-app/public/locales/en.json +0 -182
- package/dist/templates/next-app/public/locales/zh.json +0 -182
- package/dist/templates/next-app/public/next.svg +0 -1
- package/dist/templates/next-app/public/vercel.svg +0 -1
- package/dist/templates/next-app/public/window.svg +0 -1
- package/dist/templates/next-app/src/app/[locale]/admin/AdminI18nProvider.tsx +0 -37
- package/dist/templates/next-app/src/app/[locale]/admin/layout.tsx +0 -42
- package/dist/templates/next-app/src/app/[locale]/admin/locales/page.tsx +0 -153
- package/dist/templates/next-app/src/app/[locale]/admin/page.tsx +0 -20
- package/dist/templates/next-app/src/app/[locale]/admin/users/page.tsx +0 -67
- package/dist/templates/next-app/src/app/[locale]/auth/layout.tsx +0 -18
- package/dist/templates/next-app/src/app/[locale]/auth/login/LoginForm.tsx +0 -126
- package/dist/templates/next-app/src/app/[locale]/auth/login/page.tsx +0 -90
- package/dist/templates/next-app/src/app/[locale]/auth/page.tsx +0 -8
- package/dist/templates/next-app/src/app/[locale]/auth/register/RegisterForm.tsx +0 -197
- package/dist/templates/next-app/src/app/[locale]/auth/register/page.tsx +0 -90
- package/dist/templates/next-app/src/app/[locale]/layout.tsx +0 -63
- package/dist/templates/next-app/src/app/[locale]/not-found.tsx +0 -24
- package/dist/templates/next-app/src/app/[locale]/page.tsx +0 -98
- package/dist/templates/next-app/src/app/api/admin/locales/create/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/locales/import/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/locales/route.ts +0 -20
- package/dist/templates/next-app/src/app/api/admin/locales/update/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/users/route.ts +0 -20
- package/dist/templates/next-app/src/app/api/ai/completions/route.ts +0 -32
- package/dist/templates/next-app/src/app/api/auth/callback/route.ts +0 -11
- package/dist/templates/next-app/src/app/api/callback/route.ts +0 -49
- package/dist/templates/next-app/src/app/api/locales/json/route.ts +0 -33
- package/dist/templates/next-app/src/app/api/user/login/route.ts +0 -10
- package/dist/templates/next-app/src/app/api/user/logout/route.ts +0 -8
- package/dist/templates/next-app/src/app/api/user/register/route.ts +0 -11
- package/dist/templates/next-app/src/app/manifest.ts +0 -16
- package/dist/templates/next-app/src/app/robots.txt +0 -2
- package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +0 -28
- package/dist/templates/next-app/src/base/cases/AppConfig.ts +0 -40
- package/dist/templates/next-app/src/base/cases/Datetime.ts +0 -18
- package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +0 -57
- package/dist/templates/next-app/src/base/cases/DialogHandler.ts +0 -116
- package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +0 -45
- package/dist/templates/next-app/src/base/cases/NavigateBridge.ts +0 -32
- package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +0 -77
- package/dist/templates/next-app/src/base/cases/ResourceState.ts +0 -17
- package/dist/templates/next-app/src/base/cases/RouterService.ts +0 -52
- package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +0 -73
- package/dist/templates/next-app/src/base/cases/TranslateI18nUtil.ts +0 -53
- package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +0 -212
- package/dist/templates/next-app/src/base/port/AdminLayoutInterface.ts +0 -26
- package/dist/templates/next-app/src/base/port/AppApiInterface.ts +0 -36
- package/dist/templates/next-app/src/base/port/AppUserApiInterface.ts +0 -27
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +0 -25
- package/dist/templates/next-app/src/base/port/IOCInterface.ts +0 -33
- package/dist/templates/next-app/src/base/port/RouterInterface.ts +0 -11
- package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +0 -25
- package/dist/templates/next-app/src/base/port/ZodBuilderInterface.ts +0 -8
- package/dist/templates/next-app/src/base/services/AdminPageEvent.ts +0 -26
- package/dist/templates/next-app/src/base/services/AdminPageScheduler.ts +0 -42
- package/dist/templates/next-app/src/base/services/AppApiRequester.ts +0 -67
- package/dist/templates/next-app/src/base/services/AppUserGateway.ts +0 -110
- package/dist/templates/next-app/src/base/services/I18nService.ts +0 -87
- package/dist/templates/next-app/src/base/services/ResourceService.ts +0 -139
- package/dist/templates/next-app/src/base/services/UserService.ts +0 -68
- package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +0 -106
- package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +0 -87
- package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +0 -110
- package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +0 -52
- package/dist/templates/next-app/src/base/types/AppPageRouter.ts +0 -12
- package/dist/templates/next-app/src/base/types/PagesRouter.ts +0 -9
- package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +0 -76
- package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +0 -125
- package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +0 -50
- package/dist/templates/next-app/src/core/bootstraps/IocIdentifierTest.ts +0 -26
- package/dist/templates/next-app/src/core/bootstraps/PrintBootstrap.ts +0 -18
- package/dist/templates/next-app/src/core/clientIoc/ClientIOC.ts +0 -68
- package/dist/templates/next-app/src/core/clientIoc/ClientIOCRegister.ts +0 -100
- package/dist/templates/next-app/src/core/globals.ts +0 -28
- package/dist/templates/next-app/src/core/serverIoc/ServerIOC.ts +0 -80
- package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +0 -66
- package/dist/templates/next-app/src/i18n/loadMessages.ts +0 -103
- package/dist/templates/next-app/src/i18n/request.ts +0 -31
- package/dist/templates/next-app/src/i18n/routing.ts +0 -35
- package/dist/templates/next-app/src/lib/supabase/client.ts +0 -8
- package/dist/templates/next-app/src/lib/supabase/conts.ts +0 -2
- package/dist/templates/next-app/src/lib/supabase/proxy.ts +0 -84
- package/dist/templates/next-app/src/lib/supabase/server.ts +0 -38
- package/dist/templates/next-app/src/pages/[locale]/about.tsx +0 -61
- package/dist/templates/next-app/src/pages/_app.tsx +0 -50
- package/dist/templates/next-app/src/pages/_document.tsx +0 -13
- package/dist/templates/next-app/src/proxy.ts +0 -33
- package/dist/templates/next-app/src/server/AppErrorApi.ts +0 -10
- package/dist/templates/next-app/src/server/AppPageRouteParams.ts +0 -110
- package/dist/templates/next-app/src/server/AppSuccessApi.ts +0 -7
- package/dist/templates/next-app/src/server/NextApiServer.ts +0 -61
- package/dist/templates/next-app/src/server/PagesRouteParams.ts +0 -145
- package/dist/templates/next-app/src/server/PasswordEncrypt.ts +0 -18
- package/dist/templates/next-app/src/server/ServerAuth.ts +0 -81
- package/dist/templates/next-app/src/server/SupabaseBridge.ts +0 -262
- package/dist/templates/next-app/src/server/UserCredentialToken.ts +0 -53
- package/dist/templates/next-app/src/server/controllers/AdminLocalesController.ts +0 -86
- package/dist/templates/next-app/src/server/controllers/AdminUserController.ts +0 -42
- package/dist/templates/next-app/src/server/controllers/LocalesController.ts +0 -36
- package/dist/templates/next-app/src/server/controllers/UserController.ts +0 -91
- package/dist/templates/next-app/src/server/port/AIControllerInterface.ts +0 -8
- package/dist/templates/next-app/src/server/port/AdminLocalesControllerInterface.ts +0 -21
- package/dist/templates/next-app/src/server/port/AdminUserControllerInterface.ts +0 -11
- package/dist/templates/next-app/src/server/port/CrentialTokenInterface.ts +0 -5
- package/dist/templates/next-app/src/server/port/DBBridgeInterface.ts +0 -36
- package/dist/templates/next-app/src/server/port/DBTableInterface.ts +0 -12
- package/dist/templates/next-app/src/server/port/LocalesControllerInterface.ts +0 -10
- package/dist/templates/next-app/src/server/port/LocalesRepositoryInterface.ts +0 -43
- package/dist/templates/next-app/src/server/port/PaginationInterface.ts +0 -6
- package/dist/templates/next-app/src/server/port/RouteParamsnHandlerInterface.ts +0 -18
- package/dist/templates/next-app/src/server/port/ServerAuthInterface.ts +0 -15
- package/dist/templates/next-app/src/server/port/ServerInterface.ts +0 -23
- package/dist/templates/next-app/src/server/port/UserRepositoryInterface.ts +0 -15
- package/dist/templates/next-app/src/server/port/UserServiceInterface.ts +0 -14
- package/dist/templates/next-app/src/server/port/ValidatorInterface.ts +0 -23
- package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +0 -216
- package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +0 -102
- package/dist/templates/next-app/src/server/services/AIService.ts +0 -45
- package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +0 -21
- package/dist/templates/next-app/src/server/services/AdminLocalesService.ts +0 -20
- package/dist/templates/next-app/src/server/services/ApiLocaleService.ts +0 -137
- package/dist/templates/next-app/src/server/services/ApiUserService.ts +0 -29
- package/dist/templates/next-app/src/server/services/UserService.ts +0 -134
- package/dist/templates/next-app/src/server/validators/ExtendedExecutorError.ts +0 -6
- package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +0 -145
- package/dist/templates/next-app/src/server/validators/LoginValidator.ts +0 -82
- package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +0 -70
- package/dist/templates/next-app/src/server/validators/SignupVerifyValidator.ts +0 -68
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/_default.css +0 -280
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/dark.css +0 -233
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/pink.css +0 -246
- package/dist/templates/next-app/src/styles/css/antd-themes/index.css +0 -4
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/_default.css +0 -108
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/dark.css +0 -67
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/pink.css +0 -67
- package/dist/templates/next-app/src/styles/css/antd-themes/no-context.css +0 -34
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/_default.css +0 -34
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/dark.css +0 -31
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/pink.css +0 -36
- package/dist/templates/next-app/src/styles/css/antd-themes/table/_default.css +0 -44
- package/dist/templates/next-app/src/styles/css/antd-themes/table/dark.css +0 -43
- package/dist/templates/next-app/src/styles/css/antd-themes/table/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/table/pink.css +0 -43
- package/dist/templates/next-app/src/styles/css/index.css +0 -6
- package/dist/templates/next-app/src/styles/css/page.css +0 -20
- package/dist/templates/next-app/src/styles/css/scrollbar.css +0 -34
- package/dist/templates/next-app/src/styles/css/tailwind.css +0 -5
- package/dist/templates/next-app/src/styles/css/themes/_default.css +0 -30
- package/dist/templates/next-app/src/styles/css/themes/dark.css +0 -30
- package/dist/templates/next-app/src/styles/css/themes/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/themes/pink.css +0 -30
- package/dist/templates/next-app/src/styles/css/zIndex.css +0 -9
- package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +0 -150
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +0 -39
- package/dist/templates/next-app/src/uikit/components/ClientRootProvider.tsx +0 -64
- package/dist/templates/next-app/src/uikit/components/ClientSeo.tsx +0 -36
- package/dist/templates/next-app/src/uikit/components/ClinetRenderProvider.tsx +0 -42
- package/dist/templates/next-app/src/uikit/components/EditableCell.tsx +0 -118
- package/dist/templates/next-app/src/uikit/components/FeatureItem.tsx +0 -13
- package/dist/templates/next-app/src/uikit/components/IOCProvider.tsx +0 -34
- package/dist/templates/next-app/src/uikit/components/LocaleLink.tsx +0 -50
- package/dist/templates/next-app/src/uikit/components/With.tsx +0 -17
- package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportButton.tsx +0 -62
- package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +0 -28
- package/dist/templates/next-app/src/uikit/components/localesImportButton/import.module.css +0 -6
- package/dist/templates/next-app/src/uikit/components-app/AdminButton.tsx +0 -29
- package/dist/templates/next-app/src/uikit/components-app/AppBridge.tsx +0 -17
- package/dist/templates/next-app/src/uikit/components-app/AppRoutePage.tsx +0 -105
- package/dist/templates/next-app/src/uikit/components-app/AuthButton.tsx +0 -20
- package/dist/templates/next-app/src/uikit/components-app/LanguageSwitcher.tsx +0 -75
- package/dist/templates/next-app/src/uikit/components-app/LogoutButton.tsx +0 -45
- package/dist/templates/next-app/src/uikit/components-app/ThemeSwitcher.tsx +0 -144
- package/dist/templates/next-app/src/uikit/components-pages/LanguageSwitcher.tsx +0 -98
- package/dist/templates/next-app/src/uikit/components-pages/PagesRoutePage.tsx +0 -93
- package/dist/templates/next-app/src/uikit/context/IOCContext.ts +0 -25
- package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +0 -22
- package/dist/templates/next-app/src/uikit/hook/useIOC.ts +0 -37
- package/dist/templates/next-app/src/uikit/hook/useStrictEffect.ts +0 -32
- package/dist/templates/next-app/src/uikit/hook/useWarnTranslations.ts +0 -11
- package/dist/templates/next-app/src/uikit/utils/getHashParams.ts +0 -8
- package/dist/templates/next-app/src/uikit/utils/getHashVerifyEmailParams.ts +0 -42
- package/dist/templates/next-app/tailwind.config.ts +0 -8
- package/dist/templates/next-app/tsconfig.json +0 -39
- package/dist/templates/node-lib/__tests__/readJson.test.ts +0 -26
- package/dist/templates/node-lib/bin/test.js +0 -30
- package/dist/templates/node-lib/package.json +0 -66
- package/dist/templates/node-lib/rollup.config.js +0 -79
- package/dist/templates/node-lib/src/index.ts +0 -7
- package/dist/templates/node-lib/src/readJson.ts +0 -12
- package/dist/templates/node-lib/tsconfig.json +0 -23
- package/dist/templates/pack-app/README.md +0 -108
- package/dist/templates/pack-app/eslint.config.js +0 -97
- package/dist/templates/pack-app/fe-config.json +0 -35
- package/dist/templates/pack-app/package.json +0 -86
- package/dist/templates/pack-app/pnpm-workspace.yaml +0 -2
- package/dist/templates/pack-app/tsconfig.json +0 -9
- package/dist/templates/pack-app/tsconfig.test.json +0 -10
- package/dist/templates/pack-app/vite.config.ts +0 -14
- package/dist/templates/react-app/.env.template +0 -22
- package/dist/templates/react-app/.prettierignore +0 -17
- package/dist/templates/react-app/README.en.md +0 -274
- package/dist/templates/react-app/README.md +0 -273
- package/dist/templates/react-app/__tests__/__mocks__/BootstrapTest.ts +0 -16
- package/dist/templates/react-app/__tests__/__mocks__/MockAppConfig.ts +0 -48
- package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +0 -17
- package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +0 -14
- package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +0 -38
- package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +0 -53
- package/dist/templates/react-app/__tests__/__mocks__/components/TestRouter.tsx +0 -46
- package/dist/templates/react-app/__tests__/__mocks__/components/index.ts +0 -12
- package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +0 -96
- package/dist/templates/react-app/__tests__/__mocks__/i18nextHttpBackend.ts +0 -110
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOC.ts +0 -55
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +0 -74
- package/dist/templates/react-app/__tests__/setup/index.ts +0 -1
- package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +0 -64
- package/dist/templates/react-app/__tests__/src/App.structure.test.tsx +0 -115
- package/dist/templates/react-app/__tests__/src/base/cases/AppConfig.test.ts +0 -288
- package/dist/templates/react-app/__tests__/src/base/cases/DialogHandler.test.ts +0 -226
- package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +0 -178
- package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +0 -181
- package/dist/templates/react-app/__tests__/src/base/cases/PublicAssetsPath.test.ts +0 -61
- package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +0 -177
- package/dist/templates/react-app/__tests__/src/base/cases/RequestStatusCatcher.test.ts +0 -191
- package/dist/templates/react-app/__tests__/src/base/cases/RouterLoader.test.ts +0 -245
- package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +0 -240
- package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +0 -242
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +0 -135
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +0 -74
- package/dist/templates/react-app/__tests__/src/main.test.tsx +0 -46
- package/dist/templates/react-app/__tests__/src/uikit/components/BaseHeader.test.tsx +0 -97
- package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +0 -274
- package/dist/templates/react-app/config/IOCIdentifier.ts +0 -91
- package/dist/templates/react-app/config/Identifier/common/common.error.ts +0 -34
- package/dist/templates/react-app/config/Identifier/common/common.ts +0 -62
- package/dist/templates/react-app/config/Identifier/common/index.ts +0 -2
- package/dist/templates/react-app/config/Identifier/components/component.chatMessage.ts +0 -56
- package/dist/templates/react-app/config/Identifier/components/component.messageBaseList.ts +0 -103
- package/dist/templates/react-app/config/Identifier/index.ts +0 -2
- package/dist/templates/react-app/config/Identifier/pages/index.ts +0 -9
- package/dist/templates/react-app/config/Identifier/pages/page.about.ts +0 -189
- package/dist/templates/react-app/config/Identifier/pages/page.executor.ts +0 -275
- package/dist/templates/react-app/config/Identifier/pages/page.home.ts +0 -71
- package/dist/templates/react-app/config/Identifier/pages/page.identifiter.ts +0 -102
- package/dist/templates/react-app/config/Identifier/pages/page.jsonStorage.ts +0 -77
- package/dist/templates/react-app/config/Identifier/pages/page.login.ts +0 -162
- package/dist/templates/react-app/config/Identifier/pages/page.message.ts +0 -20
- package/dist/templates/react-app/config/Identifier/pages/page.register.ts +0 -159
- package/dist/templates/react-app/config/Identifier/pages/page.request.ts +0 -169
- package/dist/templates/react-app/config/app.router.ts +0 -338
- package/dist/templates/react-app/config/common.ts +0 -85
- package/dist/templates/react-app/config/feapi.mock.json +0 -34
- package/dist/templates/react-app/config/i18n/PageI18nInterface.ts +0 -53
- package/dist/templates/react-app/config/i18n/aboutI18n.ts +0 -42
- package/dist/templates/react-app/config/i18n/chatMessageI18n.ts +0 -17
- package/dist/templates/react-app/config/i18n/executorI18n.ts +0 -51
- package/dist/templates/react-app/config/i18n/homeI18n.ts +0 -24
- package/dist/templates/react-app/config/i18n/i18nConfig.ts +0 -30
- package/dist/templates/react-app/config/i18n/identifiter18n.ts +0 -30
- package/dist/templates/react-app/config/i18n/jsonStorage18n.ts +0 -27
- package/dist/templates/react-app/config/i18n/login18n.ts +0 -42
- package/dist/templates/react-app/config/i18n/messageBaseListI18n.ts +0 -22
- package/dist/templates/react-app/config/i18n/messageI18n.ts +0 -14
- package/dist/templates/react-app/config/i18n/notFoundI18n.ts +0 -34
- package/dist/templates/react-app/config/i18n/register18n.ts +0 -40
- package/dist/templates/react-app/config/i18n/request18n.ts +0 -41
- package/dist/templates/react-app/config/theme.ts +0 -21
- package/dist/templates/react-app/docs/en/bootstrap.md +0 -1891
- package/dist/templates/react-app/docs/en/components/chat-message-component.md +0 -320
- package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +0 -283
- package/dist/templates/react-app/docs/en/components/message-base-list-component.md +0 -171
- package/dist/templates/react-app/docs/en/development-guide.md +0 -1199
- package/dist/templates/react-app/docs/en/env.md +0 -1336
- package/dist/templates/react-app/docs/en/global.md +0 -509
- package/dist/templates/react-app/docs/en/i18n.md +0 -979
- package/dist/templates/react-app/docs/en/index.md +0 -802
- package/dist/templates/react-app/docs/en/ioc.md +0 -1365
- package/dist/templates/react-app/docs/en/playwright/e2e-tests.md +0 -321
- package/dist/templates/react-app/docs/en/playwright/index.md +0 -19
- package/dist/templates/react-app/docs/en/playwright/installation-summary.md +0 -332
- package/dist/templates/react-app/docs/en/playwright/overview.md +0 -222
- package/dist/templates/react-app/docs/en/playwright/quickstart.md +0 -325
- package/dist/templates/react-app/docs/en/playwright/reorganization-notes.md +0 -340
- package/dist/templates/react-app/docs/en/playwright/setup-complete.md +0 -290
- package/dist/templates/react-app/docs/en/playwright/testing-guide.md +0 -565
- package/dist/templates/react-app/docs/en/request.md +0 -423
- package/dist/templates/react-app/docs/en/router.md +0 -404
- package/dist/templates/react-app/docs/en/store.md +0 -1331
- package/dist/templates/react-app/docs/en/test-guide.md +0 -976
- package/dist/templates/react-app/docs/en/theme.md +0 -424
- package/dist/templates/react-app/docs/en/typescript-guide.md +0 -473
- package/dist/templates/react-app/docs/en/why-no-globals.md +0 -797
- package/dist/templates/react-app/docs/zh/bootstrap.md +0 -1891
- package/dist/templates/react-app/docs/zh/components/chat-message-component.md +0 -320
- package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +0 -283
- package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +0 -171
- package/dist/templates/react-app/docs/zh/development-guide.md +0 -1199
- package/dist/templates/react-app/docs/zh/env.md +0 -1336
- package/dist/templates/react-app/docs/zh/global.md +0 -511
- package/dist/templates/react-app/docs/zh/i18n.md +0 -979
- package/dist/templates/react-app/docs/zh/index.md +0 -786
- package/dist/templates/react-app/docs/zh/ioc.md +0 -1364
- package/dist/templates/react-app/docs/zh/playwright/e2e-tests.md +0 -321
- package/dist/templates/react-app/docs/zh/playwright/index.md +0 -19
- package/dist/templates/react-app/docs/zh/playwright/installation-summary.md +0 -332
- package/dist/templates/react-app/docs/zh/playwright/overview.md +0 -222
- package/dist/templates/react-app/docs/zh/playwright/quickstart.md +0 -325
- package/dist/templates/react-app/docs/zh/playwright/reorganization-notes.md +0 -340
- package/dist/templates/react-app/docs/zh/playwright/setup-complete.md +0 -290
- package/dist/templates/react-app/docs/zh/playwright/testing-guide.md +0 -565
- package/dist/templates/react-app/docs/zh/request.md +0 -427
- package/dist/templates/react-app/docs/zh/router.md +0 -408
- package/dist/templates/react-app/docs/zh/store.md +0 -1329
- package/dist/templates/react-app/docs/zh/test-guide.md +0 -976
- package/dist/templates/react-app/docs/zh/theme.md +0 -424
- package/dist/templates/react-app/docs/zh/typescript-guide.md +0 -473
- package/dist/templates/react-app/docs/zh/why-no-globals.md +0 -797
- package/dist/templates/react-app/e2e/App.spec.ts +0 -319
- package/dist/templates/react-app/e2e/fixtures/base.fixture.ts +0 -40
- package/dist/templates/react-app/e2e/main.spec.ts +0 -20
- package/dist/templates/react-app/e2e/utils/test-helpers.ts +0 -19
- package/dist/templates/react-app/eslint.config.mjs +0 -325
- package/dist/templates/react-app/index.html +0 -13
- package/dist/templates/react-app/makes/generateTs2LocalesOptions.ts +0 -26
- package/dist/templates/react-app/package.json +0 -125
- package/dist/templates/react-app/playwright.config.ts +0 -79
- package/dist/templates/react-app/postcss.config.js +0 -5
- package/dist/templates/react-app/public/locales/en/common.json +0 -235
- package/dist/templates/react-app/public/locales/zh/common.json +0 -235
- package/dist/templates/react-app/public/logo.svg +0 -1
- package/dist/templates/react-app/public/router-root/logo.svg +0 -1
- package/dist/templates/react-app/src/App.tsx +0 -35
- package/dist/templates/react-app/src/assets/react.svg +0 -1
- package/dist/templates/react-app/src/base/apis/AiApi.ts +0 -68
- package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +0 -29
- package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +0 -14
- package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +0 -86
- package/dist/templates/react-app/src/base/apis/feApi/FeApiType.ts +0 -21
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +0 -142
- package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +0 -14
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +0 -86
- package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +0 -70
- package/dist/templates/react-app/src/base/cases/AppConfig.ts +0 -123
- package/dist/templates/react-app/src/base/cases/DialogHandler.ts +0 -115
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +0 -64
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +0 -45
- package/dist/templates/react-app/src/base/cases/PublicAssetsPath.ts +0 -23
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +0 -55
- package/dist/templates/react-app/src/base/cases/RequestLogger.ts +0 -80
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +0 -40
- package/dist/templates/react-app/src/base/cases/ResourceState.ts +0 -23
- package/dist/templates/react-app/src/base/cases/RouterLoader.ts +0 -173
- package/dist/templates/react-app/src/base/cases/TranslateI18nInterface.ts +0 -26
- package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +0 -23
- package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +0 -10
- package/dist/templates/react-app/src/base/port/IOCInterface.ts +0 -38
- package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +0 -21
- package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +0 -23
- package/dist/templates/react-app/src/base/port/RequestStatusInterface.ts +0 -5
- package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +0 -29
- package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +0 -20
- package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +0 -61
- package/dist/templates/react-app/src/base/services/I18nService.ts +0 -146
- package/dist/templates/react-app/src/base/services/IdentifierService.ts +0 -162
- package/dist/templates/react-app/src/base/services/RouteService.ts +0 -115
- package/dist/templates/react-app/src/base/services/UserBootstrap.ts +0 -45
- package/dist/templates/react-app/src/base/services/UserService.ts +0 -88
- package/dist/templates/react-app/src/base/types/Page.ts +0 -47
- package/dist/templates/react-app/src/base/types/deprecated-antd.d.ts +0 -60
- package/dist/templates/react-app/src/base/types/global.d.ts +0 -8
- package/dist/templates/react-app/src/core/IOC.ts +0 -28
- package/dist/templates/react-app/src/core/bootstraps/BootstrapClient.ts +0 -108
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +0 -54
- package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +0 -26
- package/dist/templates/react-app/src/core/bootstraps/PrintBootstrap.ts +0 -14
- package/dist/templates/react-app/src/core/bootstraps/SaveAppInfo.ts +0 -28
- package/dist/templates/react-app/src/core/clientIoc/ClientIOC.ts +0 -47
- package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +0 -142
- package/dist/templates/react-app/src/core/globals.ts +0 -47
- package/dist/templates/react-app/src/main.tsx +0 -19
- package/dist/templates/react-app/src/pages/404.tsx +0 -19
- package/dist/templates/react-app/src/pages/500.tsx +0 -18
- package/dist/templates/react-app/src/pages/NoRouteFound.tsx +0 -5
- package/dist/templates/react-app/src/pages/auth/Layout.tsx +0 -27
- package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +0 -166
- package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +0 -226
- package/dist/templates/react-app/src/pages/base/AboutPage.tsx +0 -123
- package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +0 -467
- package/dist/templates/react-app/src/pages/base/HomePage.tsx +0 -81
- package/dist/templates/react-app/src/pages/base/IdentifierPage.tsx +0 -117
- package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +0 -132
- package/dist/templates/react-app/src/pages/base/Layout.tsx +0 -20
- package/dist/templates/react-app/src/pages/base/MessagePage.tsx +0 -71
- package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +0 -18
- package/dist/templates/react-app/src/pages/base/RequestPage.tsx +0 -193
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/_default.css +0 -280
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/dark.css +0 -233
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/pink.css +0 -246
- package/dist/templates/react-app/src/styles/css/antd-themes/index.css +0 -4
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/_default.css +0 -108
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/dark.css +0 -67
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/pink.css +0 -67
- package/dist/templates/react-app/src/styles/css/antd-themes/no-context.css +0 -34
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/_default.css +0 -34
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/dark.css +0 -31
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/pink.css +0 -36
- package/dist/templates/react-app/src/styles/css/antd-themes/table/_default.css +0 -44
- package/dist/templates/react-app/src/styles/css/antd-themes/table/dark.css +0 -43
- package/dist/templates/react-app/src/styles/css/antd-themes/table/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/table/pink.css +0 -43
- package/dist/templates/react-app/src/styles/css/index.css +0 -6
- package/dist/templates/react-app/src/styles/css/page.css +0 -20
- package/dist/templates/react-app/src/styles/css/scrollbar.css +0 -34
- package/dist/templates/react-app/src/styles/css/tailwind.css +0 -5
- package/dist/templates/react-app/src/styles/css/themes/_default.css +0 -30
- package/dist/templates/react-app/src/styles/css/themes/dark.css +0 -30
- package/dist/templates/react-app/src/styles/css/themes/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/themes/pink.css +0 -30
- package/dist/templates/react-app/src/styles/css/zIndex.css +0 -9
- package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +0 -72
- package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +0 -41
- package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +0 -22
- package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +0 -136
- package/dist/templates/react-app/src/uikit/components/AppRouterProvider.tsx +0 -35
- package/dist/templates/react-app/src/uikit/components/BaseHeader.tsx +0 -51
- package/dist/templates/react-app/src/uikit/components/BaseLayoutProvider.tsx +0 -44
- package/dist/templates/react-app/src/uikit/components/BaseRouteProvider.tsx +0 -21
- package/dist/templates/react-app/src/uikit/components/BaseRouteSeo.tsx +0 -18
- package/dist/templates/react-app/src/uikit/components/BootstrapsProvider.tsx +0 -11
- package/dist/templates/react-app/src/uikit/components/ClientSeo.tsx +0 -62
- package/dist/templates/react-app/src/uikit/components/ComboProvider.tsx +0 -38
- package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +0 -78
- package/dist/templates/react-app/src/uikit/components/Loading.tsx +0 -49
- package/dist/templates/react-app/src/uikit/components/LocaleLink.tsx +0 -43
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +0 -58
- package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +0 -258
- package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +0 -19
- package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +0 -137
- package/dist/templates/react-app/src/uikit/components/With.tsx +0 -17
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +0 -205
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatRoot.tsx +0 -21
- package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +0 -108
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +0 -282
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageItem.tsx +0 -102
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessagesList.tsx +0 -86
- package/dist/templates/react-app/src/uikit/contexts/BaseRouteContext.ts +0 -42
- package/dist/templates/react-app/src/uikit/contexts/IOCContext.ts +0 -13
- package/dist/templates/react-app/src/uikit/hooks/useAppTranslation.ts +0 -26
- package/dist/templates/react-app/src/uikit/hooks/useI18nInterface.ts +0 -25
- package/dist/templates/react-app/src/uikit/hooks/useIOC.ts +0 -35
- package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +0 -21
- package/dist/templates/react-app/src/uikit/hooks/useRouterI18nGuard.ts +0 -25
- package/dist/templates/react-app/src/uikit/hooks/useStrictEffect.ts +0 -31
- package/dist/templates/react-app/src/vite-env.d.ts +0 -1
- package/dist/templates/react-app/tailwind.config.js +0 -4
- package/dist/templates/react-app/tsconfig.app.json +0 -36
- package/dist/templates/react-app/tsconfig.e2e.json +0 -24
- package/dist/templates/react-app/tsconfig.json +0 -22
- package/dist/templates/react-app/tsconfig.node.json +0 -27
- package/dist/templates/react-app/tsconfig.test.json +0 -18
- package/dist/templates/react-app/vite.config.ts +0 -144
|
@@ -1,1336 +0,0 @@
|
|
|
1
|
-
# 环境变量管理
|
|
2
|
-
|
|
3
|
-
## 📋 目录
|
|
4
|
-
|
|
5
|
-
- [什么是环境变量管理](#-什么是环境变量管理)
|
|
6
|
-
- [为什么需要环境变量](#-为什么需要环境变量)
|
|
7
|
-
- [工作原理](#-工作原理)
|
|
8
|
-
- [项目中的实现](#-项目中的实现)
|
|
9
|
-
- [多环境配置](#-多环境配置)
|
|
10
|
-
- [环境变量注入](#-环境变量注入)
|
|
11
|
-
- [AppConfig 使用](#-appconfig-使用)
|
|
12
|
-
- [高级用法](#-高级用法)
|
|
13
|
-
- [测试配置](#-测试配置)
|
|
14
|
-
- [最佳实践](#-最佳实践)
|
|
15
|
-
- [常见问题](#-常见问题)
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## 🎯 什么是环境变量管理
|
|
20
|
-
|
|
21
|
-
环境变量管理是 Bootstrap 架构的核心组成部分,负责在不同环境(开发、测试、生产)中使用不同的配置,并通过 **自动注入** 的方式将配置传递给应用。
|
|
22
|
-
|
|
23
|
-
### 核心流程
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
启动应用 → Vite 加载 .env 文件 → Bootstrap 初始化 → 注入环境变量到 AppConfig → IOC 容器 → 应用使用
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### 关键概念
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
┌─────────────────────────────────────────────────┐
|
|
33
|
-
│ 环境变量管理系统 │
|
|
34
|
-
│ ┌───────────────────────────────────────────┐ │
|
|
35
|
-
│ │ 1. Vite --mode 选择环境 │ │
|
|
36
|
-
│ │ 2. 加载对应的 .env 文件 │ │
|
|
37
|
-
│ │ 3. envConfig 插件预处理 │ │
|
|
38
|
-
│ │ 4. Bootstrap 注入到 AppConfig │ │
|
|
39
|
-
│ │ 5. 注册到 IOC 容器 │ │
|
|
40
|
-
│ │ 6. 应用通过 IOC 获取配置 │ │
|
|
41
|
-
│ └───────────────────────────────────────────┘ │
|
|
42
|
-
└─────────────────────────────────────────────────┘
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## 🤔 为什么需要环境变量
|
|
48
|
-
|
|
49
|
-
### 问题:硬编码配置的痛点
|
|
50
|
-
|
|
51
|
-
#### ❌ 传统方式:配置散落各处
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
// ❌ 问题 1:API 地址硬编码在代码中
|
|
55
|
-
function fetchUserInfo() {
|
|
56
|
-
// 😰 开发环境和生产环境的 API 地址不同,每次切换都要改代码
|
|
57
|
-
return fetch('http://localhost:3000/api/user');
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ❌ 问题 2:配置散落在各个文件
|
|
61
|
-
function saveToken(token: string) {
|
|
62
|
-
// 😰 存储键名硬编码,难以统一管理
|
|
63
|
-
localStorage.setItem('user_token', token);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ❌ 问题 3:敏感信息直接写在代码中
|
|
67
|
-
function callAI(prompt: string) {
|
|
68
|
-
// 😰 API Key 直接暴露在代码中,存在安全风险
|
|
69
|
-
return fetch('https://api.openai.com/v1/chat', {
|
|
70
|
-
headers: {
|
|
71
|
-
Authorization: 'Bearer sk-xxxxxxxxxxxx' // 😰 危险!
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ❌ 问题 4:环境切换困难
|
|
77
|
-
if (window.location.host === 'localhost:3000') {
|
|
78
|
-
// 😰 需要手动判断环境
|
|
79
|
-
apiUrl = 'http://localhost:3000/api';
|
|
80
|
-
} else if (window.location.host === 'staging.example.com') {
|
|
81
|
-
apiUrl = 'https://api.staging.example.com';
|
|
82
|
-
} else {
|
|
83
|
-
apiUrl = 'https://api.production.com';
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
**问题总结:**
|
|
88
|
-
|
|
89
|
-
- 😰 **配置散落** - 配置分散在多个文件中,难以管理
|
|
90
|
-
- 😰 **环境切换困难** - 需要手动修改代码或使用复杂的条件判断
|
|
91
|
-
- 😰 **安全风险** - 敏感信息可能被提交到代码仓库
|
|
92
|
-
- 😰 **难以测试** - 测试时需要 mock 大量硬编码的值
|
|
93
|
-
- 😰 **团队协作困难** - 每个开发者的本地配置可能不同
|
|
94
|
-
|
|
95
|
-
#### ✅ 解决方案:环境变量 + AppConfig
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
// ✅ 1. 环境变量文件(不同环境不同配置)
|
|
99
|
-
// .env.localhost
|
|
100
|
-
VITE_API_BASE_URL=http://localhost:3000/api
|
|
101
|
-
VITE_AI_API_TOKEN=sk-dev-xxxxx
|
|
102
|
-
|
|
103
|
-
// .env.staging
|
|
104
|
-
VITE_API_BASE_URL=https://api.staging.example.com
|
|
105
|
-
VITE_AI_API_TOKEN=sk-staging-xxxxx
|
|
106
|
-
|
|
107
|
-
// .env.production
|
|
108
|
-
VITE_API_BASE_URL=https://api.production.com
|
|
109
|
-
VITE_AI_API_TOKEN=sk-prod-xxxxx
|
|
110
|
-
|
|
111
|
-
// ✅ 2. AppConfig 统一管理配置
|
|
112
|
-
export class AppConfig {
|
|
113
|
-
readonly feApiBaseUrl = ''; // ← 自动注入
|
|
114
|
-
readonly aiApiToken = ''; // ← 自动注入
|
|
115
|
-
readonly userTokenStorageKey = '__fe_user_token__';
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// ✅ 3. 通过 IOC 容器获取配置
|
|
119
|
-
@injectable()
|
|
120
|
-
export class UserService {
|
|
121
|
-
constructor(
|
|
122
|
-
@inject(IOCIdentifier.AppConfig) private config: AppConfig
|
|
123
|
-
) {}
|
|
124
|
-
|
|
125
|
-
async fetchUserInfo() {
|
|
126
|
-
// ✅ 从配置中获取 API 地址,自动适配环境
|
|
127
|
-
return fetch(`${this.config.feApiBaseUrl}/user`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// ✅ 4. 运行时切换环境(无需修改代码)
|
|
132
|
-
npm run dev # localhost 环境
|
|
133
|
-
npm run dev:staging # staging 环境
|
|
134
|
-
npm run build:production # production 环境
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
**优势:**
|
|
138
|
-
|
|
139
|
-
- ✅ **集中管理** - 所有配置在 AppConfig 中统一管理
|
|
140
|
-
- ✅ **环境切换简单** - 只需切换运行命令
|
|
141
|
-
- ✅ **安全** - 敏感信息通过 `.env.local` 管理,不提交到仓库
|
|
142
|
-
- ✅ **易于测试** - 测试时可以轻松 mock AppConfig
|
|
143
|
-
- ✅ **团队协作友好** - 每个开发者可以有自己的 `.env.local`
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
## ⚙️ 工作原理
|
|
148
|
-
|
|
149
|
-
### 环境变量加载流程
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
┌────────────────────────────────────────────────────────────┐
|
|
153
|
-
│ 1. package.json: 定义启动命令 │
|
|
154
|
-
│ npm run dev → vite --mode localhost │
|
|
155
|
-
│ npm run dev:staging → vite --mode staging │
|
|
156
|
-
│ npm run build:production → vite build --mode production │
|
|
157
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
158
|
-
↓
|
|
159
|
-
┌────────────────────────────────────────────────────────────┐
|
|
160
|
-
│ 2. Vite: 根据 --mode 加载对应的 .env 文件 │
|
|
161
|
-
│ --mode localhost → .env.localhost │
|
|
162
|
-
│ --mode staging → .env.staging │
|
|
163
|
-
│ --mode production → .env.production │
|
|
164
|
-
│ │
|
|
165
|
-
│ 加载优先级:.env.local > .env.[mode] > .env │
|
|
166
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
167
|
-
↓
|
|
168
|
-
┌────────────────────────────────────────────────────────────┐
|
|
169
|
-
│ 3. vite.config.ts: envConfig 插件预处理 │
|
|
170
|
-
│ - 注入 APP_NAME、APP_VERSION 等 │
|
|
171
|
-
│ - 设置环境变量前缀 (VITE_) │
|
|
172
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
173
|
-
↓
|
|
174
|
-
┌────────────────────────────────────────────────────────────┐
|
|
175
|
-
│ 4. BootstrapClient: 初始化 Bootstrap │
|
|
176
|
-
│ envOptions: { │
|
|
177
|
-
│ target: appConfig, // 注入目标 │
|
|
178
|
-
│ source: import.meta.env, // 环境变量源 │
|
|
179
|
-
│ prefix: 'VITE_', // 前缀 │
|
|
180
|
-
│ blackList: ['env', 'userNodeEnv'] // 黑名单 │
|
|
181
|
-
│ } │
|
|
182
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
183
|
-
↓
|
|
184
|
-
┌────────────────────────────────────────────────────────────┐
|
|
185
|
-
│ 5. InjectEnv 插件: 自动注入环境变量到 AppConfig │
|
|
186
|
-
│ - VITE_APP_NAME → appConfig.appName │
|
|
187
|
-
│ - VITE_FE_API_BASE_URL → appConfig.feApiBaseUrl │
|
|
188
|
-
│ - VITE_AI_API_TOKEN → appConfig.aiApiToken │
|
|
189
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
190
|
-
↓
|
|
191
|
-
┌────────────────────────────────────────────────────────────┐
|
|
192
|
-
│ 6. IOC 容器: 注册 AppConfig │
|
|
193
|
-
│ container.bind(IOCIdentifier.AppConfig).toConstantValue │
|
|
194
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
195
|
-
↓
|
|
196
|
-
┌────────────────────────────────────────────────────────────┐
|
|
197
|
-
│ 7. 应用使用: 通过 IOC 获取配置 │
|
|
198
|
-
│ const config = useIOC('AppConfig'); │
|
|
199
|
-
│ console.log(config.feApiBaseUrl); │
|
|
200
|
-
└────────────────────────────────────────────────────────────┘
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### 命名转换规则
|
|
204
|
-
|
|
205
|
-
环境变量名会自动转换为 AppConfig 属性名:
|
|
206
|
-
|
|
207
|
-
```
|
|
208
|
-
VITE_APP_NAME → appName
|
|
209
|
-
VITE_FE_API_BASE_URL → feApiBaseUrl
|
|
210
|
-
VITE_AI_API_TOKEN → aiApiToken
|
|
211
|
-
VITE_USER_TOKEN_STORAGE_KEY → userTokenStorageKey
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
**转换规则:**
|
|
215
|
-
|
|
216
|
-
1. 移除前缀 (`VITE_`)
|
|
217
|
-
2. 将下划线分隔转换为驼峰命名
|
|
218
|
-
3. 匹配 AppConfig 中的属性名
|
|
219
|
-
|
|
220
|
-
---
|
|
221
|
-
|
|
222
|
-
## 🛠️ 项目中的实现
|
|
223
|
-
|
|
224
|
-
### 1. 定义启动命令
|
|
225
|
-
|
|
226
|
-
```json
|
|
227
|
-
// package.json
|
|
228
|
-
{
|
|
229
|
-
"scripts": {
|
|
230
|
-
"dev": "vite --mode localhost",
|
|
231
|
-
"dev:staging": "vite --mode staging",
|
|
232
|
-
"dev:prod": "vite --mode production",
|
|
233
|
-
"build": "npm run lint && vite build",
|
|
234
|
-
"build:staging": "npm run lint && vite build --mode staging",
|
|
235
|
-
"build:production": "npm run lint && vite build --mode production"
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
**说明:**
|
|
241
|
-
|
|
242
|
-
- `--mode` 参数决定加载哪个 `.env` 文件
|
|
243
|
-
- 开发环境:使用 `localhost` 模式
|
|
244
|
-
- 测试环境:使用 `staging` 模式
|
|
245
|
-
- 生产环境:使用 `production` 模式
|
|
246
|
-
|
|
247
|
-
### 2. 配置 Vite
|
|
248
|
-
|
|
249
|
-
```typescript
|
|
250
|
-
// vite.config.ts
|
|
251
|
-
import { defineConfig } from 'vitest/config';
|
|
252
|
-
import { envPrefix } from './config/common';
|
|
253
|
-
import { name, version } from './package.json';
|
|
254
|
-
import envConfig from '@qlover/corekit-bridge/build/vite-env-config';
|
|
255
|
-
|
|
256
|
-
export default defineConfig({
|
|
257
|
-
plugins: [
|
|
258
|
-
// ✅ envConfig 插件:预处理环境变量
|
|
259
|
-
envConfig({
|
|
260
|
-
envPops: true, // 启用环境变量处理
|
|
261
|
-
envPrefix, // 环境变量前缀: 'VITE_'
|
|
262
|
-
records: [
|
|
263
|
-
['APP_NAME', name], // 注入应用名称
|
|
264
|
-
['APP_VERSION', version] // 注入应用版本
|
|
265
|
-
]
|
|
266
|
-
})
|
|
267
|
-
// ... 其他插件
|
|
268
|
-
],
|
|
269
|
-
envPrefix: envPrefix, // Vite 环境变量前缀
|
|
270
|
-
server: {
|
|
271
|
-
port: Number(process.env.VITE_SERVER_PORT || 3200)
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
**关键配置:**
|
|
277
|
-
|
|
278
|
-
- `envConfig` 插件负责预处理环境变量
|
|
279
|
-
- `records` 可以注入额外的变量(如 package.json 中的信息)
|
|
280
|
-
- `envPrefix` 设置为 `'VITE_'`,只有此前缀的变量会被暴露给客户端
|
|
281
|
-
|
|
282
|
-
### 3. 定义公共配置
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
// config/common.ts
|
|
286
|
-
export const envPrefix = 'VITE_';
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* 启动器环境变量注入黑名单
|
|
290
|
-
* 这些属性不会从环境变量注入
|
|
291
|
-
*/
|
|
292
|
-
export const envBlackList = ['env', 'userNodeEnv'];
|
|
293
|
-
|
|
294
|
-
export const browserGlobalsName = 'feGlobals';
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
### 4. 定义 AppConfig
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
// src/base/cases/AppConfig.ts
|
|
301
|
-
import type { EnvConfigInterface } from '@qlover/corekit-bridge';
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* 应用配置类
|
|
305
|
-
*
|
|
306
|
-
* 所有属性都会在 Bootstrap 初始化时自动注入对应的环境变量值
|
|
307
|
-
*
|
|
308
|
-
* 环境变量命名规则:
|
|
309
|
-
* - 属性名会转换为大写下划线格式
|
|
310
|
-
* - 添加 VITE_ 前缀
|
|
311
|
-
*
|
|
312
|
-
* 示例:
|
|
313
|
-
* - appName → VITE_APP_NAME
|
|
314
|
-
* - feApiBaseUrl → VITE_FE_API_BASE_URL
|
|
315
|
-
* - aiApiToken → VITE_AI_API_TOKEN
|
|
316
|
-
*/
|
|
317
|
-
export class AppConfig implements EnvConfigInterface {
|
|
318
|
-
constructor(
|
|
319
|
-
/**
|
|
320
|
-
* 当前环境模式
|
|
321
|
-
* @description 从 Vite 的 MODE 自动设置
|
|
322
|
-
*/
|
|
323
|
-
readonly env: string = import.meta.env.VITE_USER_NODE_ENV
|
|
324
|
-
) {}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* 应用名称
|
|
328
|
-
* @description 从 VITE_APP_NAME 环境变量注入
|
|
329
|
-
*/
|
|
330
|
-
readonly appName = '';
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* 应用版本
|
|
334
|
-
* @description 从 VITE_APP_VERSION 环境变量注入
|
|
335
|
-
*/
|
|
336
|
-
readonly appVersion = '';
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* 用户令牌存储键
|
|
340
|
-
* @description 从 VITE_USER_TOKEN_STORAGE_KEY 环境变量注入
|
|
341
|
-
*/
|
|
342
|
-
readonly userTokenStorageKey = '__fe_user_token__';
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* 用户信息存储键
|
|
346
|
-
* @description 从 VITE_USER_INFO_STORAGE_KEY 环境变量注入
|
|
347
|
-
*/
|
|
348
|
-
readonly userInfoStorageKey = '__fe_user_info__';
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* 前端 API 基础 URL
|
|
352
|
-
* @description 从 VITE_FE_API_BASE_URL 环境变量注入
|
|
353
|
-
*/
|
|
354
|
-
readonly feApiBaseUrl = '';
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* 用户 API 基础 URL
|
|
358
|
-
* @description 从 VITE_USER_API_BASE_URL 环境变量注入
|
|
359
|
-
*/
|
|
360
|
-
readonly userApiBaseUrl = '';
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* AI API 基础 URL
|
|
364
|
-
* @description 从 VITE_AI_API_BASE_URL 环境变量注入
|
|
365
|
-
*/
|
|
366
|
-
readonly aiApiBaseUrl = 'https://api.openai.com/v1';
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* AI API 令牌
|
|
370
|
-
* @description 从 VITE_AI_API_TOKEN 环境变量注入
|
|
371
|
-
*/
|
|
372
|
-
readonly aiApiToken = '';
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* AI API 令牌前缀
|
|
376
|
-
* @description 从 VITE_AI_API_TOKEN_PREFIX 环境变量注入
|
|
377
|
-
*/
|
|
378
|
-
readonly aiApiTokenPrefix = 'Bearer';
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* 是否需要 AI API 令牌
|
|
382
|
-
* @description 从 VITE_AI_API_REQUIRE_TOKEN 环境变量注入
|
|
383
|
-
*/
|
|
384
|
-
readonly aiApiRequireToken = true;
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* 默认登录用户名
|
|
388
|
-
* @description 从 VITE_LOGIN_USER 环境变量注入
|
|
389
|
-
*/
|
|
390
|
-
readonly loginUser = '';
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* 默认登录密码
|
|
394
|
-
* @description 从 VITE_LOGIN_PASSWORD 环境变量注入
|
|
395
|
-
*/
|
|
396
|
-
readonly loginPassword = '';
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* OpenAI 可用模型列表
|
|
400
|
-
*/
|
|
401
|
-
readonly openAiModels = [
|
|
402
|
-
'gpt-4o-mini',
|
|
403
|
-
'gpt-3.5-turbo',
|
|
404
|
-
'gpt-3.5-turbo-2',
|
|
405
|
-
'gpt-4',
|
|
406
|
-
'gpt-4-32k'
|
|
407
|
-
];
|
|
408
|
-
|
|
409
|
-
/**
|
|
410
|
-
* OpenAI API 基础 URL
|
|
411
|
-
* @description 从 VITE_OPEN_AI_BASE_URL 环境变量注入
|
|
412
|
-
*/
|
|
413
|
-
readonly openAiBaseUrl = '';
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* OpenAI API 令牌
|
|
417
|
-
* @description 从 VITE_OPEN_AI_TOKEN 环境变量注入
|
|
418
|
-
*/
|
|
419
|
-
readonly openAiToken = '';
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* OpenAI API 令牌前缀
|
|
423
|
-
* @description 从 VITE_OPEN_AI_TOKEN_PREFIX 环境变量注入
|
|
424
|
-
*/
|
|
425
|
-
readonly openAiTokenPrefix = '';
|
|
426
|
-
|
|
427
|
-
/**
|
|
428
|
-
* 是否需要 OpenAI API 令牌
|
|
429
|
-
* @description 从 VITE_OPEN_AI_REQUIRE_TOKEN 环境变量注入
|
|
430
|
-
*/
|
|
431
|
-
readonly openAiRequireToken = true;
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* 项目启动 URL
|
|
435
|
-
* @description 从 Bootstrap 注入的 BOOT_HREF
|
|
436
|
-
*/
|
|
437
|
-
readonly bootHref = '';
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* 是否为生产环境
|
|
441
|
-
*/
|
|
442
|
-
get isProduction(): boolean {
|
|
443
|
-
return this.env === 'production';
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
### 5. Bootstrap 配置
|
|
449
|
-
|
|
450
|
-
```typescript
|
|
451
|
-
// src/core/bootstraps/BootstrapClient.ts
|
|
452
|
-
import { envBlackList, envPrefix, browserGlobalsName } from '@config/common';
|
|
453
|
-
import { Bootstrap } from '@qlover/corekit-bridge';
|
|
454
|
-
import * as globals from '../globals';
|
|
455
|
-
|
|
456
|
-
export class BootstrapClient {
|
|
457
|
-
static async main(args: BootstrapClientArgs) {
|
|
458
|
-
const { root, bootHref, ioc, iocRegister } = args;
|
|
459
|
-
const { logger, appConfig } = globals;
|
|
460
|
-
|
|
461
|
-
// 创建 IOC 容器
|
|
462
|
-
const IOC = ioc.create({
|
|
463
|
-
pathname: bootHref,
|
|
464
|
-
appConfig: appConfig
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
// 创建 Bootstrap 实例
|
|
468
|
-
const bootstrap = new Bootstrap({
|
|
469
|
-
root,
|
|
470
|
-
logger,
|
|
471
|
-
ioc: {
|
|
472
|
-
manager: IOC,
|
|
473
|
-
register: iocRegister
|
|
474
|
-
},
|
|
475
|
-
// ✅ 环境变量注入配置
|
|
476
|
-
envOptions: {
|
|
477
|
-
target: appConfig, // 注入目标:AppConfig 实例
|
|
478
|
-
source: Object.assign({}, import.meta.env, {
|
|
479
|
-
[envPrefix + 'BOOT_HREF']: bootHref // 额外注入启动 URL
|
|
480
|
-
}),
|
|
481
|
-
prefix: envPrefix, // 环境变量前缀:'VITE_'
|
|
482
|
-
blackList: envBlackList // 黑名单:['env', 'userNodeEnv']
|
|
483
|
-
},
|
|
484
|
-
// 全局变量封装配置
|
|
485
|
-
globalOptions: {
|
|
486
|
-
sources: globals,
|
|
487
|
-
target: browserGlobalsName
|
|
488
|
-
}
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
try {
|
|
492
|
-
logger.info('bootstrap start...');
|
|
493
|
-
|
|
494
|
-
// ✅ 初始化 Bootstrap(此时会执行环境变量注入)
|
|
495
|
-
await bootstrap.initialize();
|
|
496
|
-
|
|
497
|
-
// 注册业务插件
|
|
498
|
-
const bootstrapsRegistry = new BootstrapsRegistry(IOC);
|
|
499
|
-
await bootstrap.use(bootstrapsRegistry.register()).start();
|
|
500
|
-
|
|
501
|
-
logger.info('bootstrap completed successfully');
|
|
502
|
-
} catch (error) {
|
|
503
|
-
logger.error(`${appConfig.appName} startup error:`, error);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
return args;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
**关键流程:**
|
|
512
|
-
|
|
513
|
-
1. `appConfig` 是一个 AppConfig 实例,所有属性都有默认值
|
|
514
|
-
2. `bootstrap.initialize()` 时会执行 `InjectEnv` 插件
|
|
515
|
-
3. `InjectEnv` 插件遍历 `appConfig` 的属性,从 `import.meta.env` 中查找对应的环境变量
|
|
516
|
-
4. 如果找到环境变量且值不为空,则覆盖默认值
|
|
517
|
-
5. 最后 `appConfig` 被注册到 IOC 容器中
|
|
518
|
-
|
|
519
|
-
---
|
|
520
|
-
|
|
521
|
-
## 🌍 多环境配置
|
|
522
|
-
|
|
523
|
-
### 环境文件结构
|
|
524
|
-
|
|
525
|
-
```
|
|
526
|
-
项目根目录/
|
|
527
|
-
├── .env # 默认配置(所有环境共享)
|
|
528
|
-
├── .env.localhost # 本地开发环境
|
|
529
|
-
├── .env.staging # 测试环境
|
|
530
|
-
├── .env.production # 生产环境
|
|
531
|
-
├── .env.local # 本地覆盖配置(不提交到 git)
|
|
532
|
-
└── .env.template # 环境变量模板(提交到 git)
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
### 加载优先级
|
|
536
|
-
|
|
537
|
-
```
|
|
538
|
-
.env.local > .env.[mode] > .env
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
**示例:**
|
|
542
|
-
|
|
543
|
-
```bash
|
|
544
|
-
# 运行:npm run dev (vite --mode localhost)
|
|
545
|
-
# 加载顺序:
|
|
546
|
-
# 1. .env.local # 优先级最高
|
|
547
|
-
# 2. .env.localhost # 其次
|
|
548
|
-
# 3. .env # 最后
|
|
549
|
-
|
|
550
|
-
# 运行:npm run build:production (vite build --mode production)
|
|
551
|
-
# 加载顺序:
|
|
552
|
-
# 1. .env.local
|
|
553
|
-
# 2. .env.production
|
|
554
|
-
# 3. .env
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
### 示例 1:默认配置
|
|
558
|
-
|
|
559
|
-
```bash
|
|
560
|
-
# .env
|
|
561
|
-
# 所有环境共享的配置
|
|
562
|
-
|
|
563
|
-
VITE_APP_NAME=MyApp
|
|
564
|
-
VITE_USER_TOKEN_STORAGE_KEY=__fe_user_token__
|
|
565
|
-
VITE_USER_INFO_STORAGE_KEY=__fe_user_info__
|
|
566
|
-
VITE_AI_API_TOKEN_PREFIX=Bearer
|
|
567
|
-
VITE_AI_API_REQUIRE_TOKEN=true
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
### 示例 2:本地开发环境
|
|
571
|
-
|
|
572
|
-
```bash
|
|
573
|
-
# .env.localhost
|
|
574
|
-
# 本地开发环境配置
|
|
575
|
-
|
|
576
|
-
# API 配置
|
|
577
|
-
VITE_FE_API_BASE_URL=http://localhost:3000/api
|
|
578
|
-
VITE_USER_API_BASE_URL=http://localhost:3000/api/user
|
|
579
|
-
VITE_AI_API_BASE_URL=http://localhost:3001/v1
|
|
580
|
-
|
|
581
|
-
# AI 配置(开发环境可能使用本地 Mock)
|
|
582
|
-
VITE_AI_API_TOKEN=sk-dev-xxxxx
|
|
583
|
-
VITE_AI_API_REQUIRE_TOKEN=false
|
|
584
|
-
|
|
585
|
-
# 调试配置
|
|
586
|
-
VITE_LOG_LEVEL=debug
|
|
587
|
-
VITE_DEBUG=true
|
|
588
|
-
|
|
589
|
-
# 默认登录信息(方便开发)
|
|
590
|
-
VITE_LOGIN_USER=admin
|
|
591
|
-
VITE_LOGIN_PASSWORD=admin123
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
### 示例 3:测试环境
|
|
595
|
-
|
|
596
|
-
```bash
|
|
597
|
-
# .env.staging
|
|
598
|
-
# 测试环境配置
|
|
599
|
-
|
|
600
|
-
# API 配置
|
|
601
|
-
VITE_FE_API_BASE_URL=https://api.staging.example.com
|
|
602
|
-
VITE_USER_API_BASE_URL=https://api.staging.example.com/user
|
|
603
|
-
VITE_AI_API_BASE_URL=https://api.staging.example.com/ai
|
|
604
|
-
|
|
605
|
-
# AI 配置
|
|
606
|
-
VITE_AI_API_TOKEN=sk-staging-xxxxx
|
|
607
|
-
VITE_AI_API_REQUIRE_TOKEN=true
|
|
608
|
-
|
|
609
|
-
# 调试配置
|
|
610
|
-
VITE_LOG_LEVEL=info
|
|
611
|
-
VITE_DEBUG=true
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
### 示例 4:生产环境
|
|
615
|
-
|
|
616
|
-
```bash
|
|
617
|
-
# .env.production
|
|
618
|
-
# 生产环境配置
|
|
619
|
-
|
|
620
|
-
# API 配置
|
|
621
|
-
VITE_FE_API_BASE_URL=https://api.example.com
|
|
622
|
-
VITE_USER_API_BASE_URL=https://api.example.com/user
|
|
623
|
-
VITE_AI_API_BASE_URL=https://api.openai.com/v1
|
|
624
|
-
|
|
625
|
-
# AI 配置
|
|
626
|
-
VITE_AI_API_TOKEN=sk-prod-xxxxx
|
|
627
|
-
VITE_AI_API_REQUIRE_TOKEN=true
|
|
628
|
-
|
|
629
|
-
# 调试配置
|
|
630
|
-
VITE_LOG_LEVEL=error
|
|
631
|
-
VITE_DEBUG=false
|
|
632
|
-
```
|
|
633
|
-
|
|
634
|
-
### 示例 5:本地覆盖配置
|
|
635
|
-
|
|
636
|
-
```bash
|
|
637
|
-
# .env.local
|
|
638
|
-
# 本地个人配置,不提交到 git
|
|
639
|
-
|
|
640
|
-
# 覆盖 AI API Token(使用自己的 Key)
|
|
641
|
-
VITE_AI_API_TOKEN=sk-my-personal-key
|
|
642
|
-
|
|
643
|
-
# 覆盖 API 地址(连接到自己的本地服务)
|
|
644
|
-
VITE_FE_API_BASE_URL=http://192.168.1.100:3000/api
|
|
645
|
-
|
|
646
|
-
# 启用特定功能
|
|
647
|
-
VITE_ENABLE_EXPERIMENTAL_FEATURES=true
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
### 示例 6:环境变量模板
|
|
651
|
-
|
|
652
|
-
```bash
|
|
653
|
-
# .env.template
|
|
654
|
-
# 环境变量模板,提交到 git 供团队参考
|
|
655
|
-
|
|
656
|
-
# ===== 必填配置 =====
|
|
657
|
-
VITE_FE_API_BASE_URL=https://your-api-url.com
|
|
658
|
-
VITE_AI_API_TOKEN=your-ai-api-token-here
|
|
659
|
-
|
|
660
|
-
# ===== 可选配置 =====
|
|
661
|
-
VITE_LOGIN_USER=your-default-username
|
|
662
|
-
VITE_LOGIN_PASSWORD=your-default-password
|
|
663
|
-
|
|
664
|
-
# ===== 说明 =====
|
|
665
|
-
# 1. 复制此文件为 .env.local
|
|
666
|
-
# 2. 填写实际的配置值
|
|
667
|
-
# 3. .env.local 不会被提交到 git
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
---
|
|
671
|
-
|
|
672
|
-
## 🔄 环境变量注入
|
|
673
|
-
|
|
674
|
-
### InjectEnv 插件工作原理
|
|
675
|
-
|
|
676
|
-
```typescript
|
|
677
|
-
// @qlover/corekit-bridge/src/core/bootstrap/plugins/InjectEnv.ts (简化版)
|
|
678
|
-
export class InjectEnv implements BootstrapExecutorPlugin {
|
|
679
|
-
readonly pluginName = 'InjectEnv';
|
|
680
|
-
|
|
681
|
-
constructor(protected options: InjectEnvConfig) {}
|
|
682
|
-
|
|
683
|
-
/**
|
|
684
|
-
* 在 Bootstrap 初始化前执行
|
|
685
|
-
*/
|
|
686
|
-
onBefore(): void {
|
|
687
|
-
const { target, source, prefix, blackList } = this.options;
|
|
688
|
-
|
|
689
|
-
// 遍历目标对象的所有属性
|
|
690
|
-
for (const key in target) {
|
|
691
|
-
// 跳过黑名单中的属性
|
|
692
|
-
if (blackList.includes(key)) {
|
|
693
|
-
continue;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
const currentValue = target[key as keyof typeof target];
|
|
697
|
-
|
|
698
|
-
// 获取对应的环境变量值
|
|
699
|
-
const envValue = this.getEnvValue(key, currentValue);
|
|
700
|
-
|
|
701
|
-
// 如果环境变量存在且与默认值不同,则注入
|
|
702
|
-
if (!this.isEmpty(envValue) && envValue !== currentValue) {
|
|
703
|
-
target[key as keyof typeof target] = envValue;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
/**
|
|
709
|
-
* 获取环境变量值
|
|
710
|
-
*/
|
|
711
|
-
private getEnvValue<D>(key: string, defaultValue?: D): D {
|
|
712
|
-
const { prefix = '', source = {} } = this.options;
|
|
713
|
-
|
|
714
|
-
// 将驼峰命名转换为大写下划线命名
|
|
715
|
-
// appName → APP_NAME
|
|
716
|
-
// feApiBaseUrl → FE_API_BASE_URL
|
|
717
|
-
const formattedKey = key.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase();
|
|
718
|
-
|
|
719
|
-
// 添加前缀
|
|
720
|
-
const envKey = `${prefix}${formattedKey}`;
|
|
721
|
-
|
|
722
|
-
// 获取环境变量值
|
|
723
|
-
const value = source[envKey];
|
|
724
|
-
|
|
725
|
-
// 如果是 JSON 字符串,则解析
|
|
726
|
-
if (typeof value === 'string' && this.isJSONString(value)) {
|
|
727
|
-
return JSON.parse(value);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
return (value ?? defaultValue) as D;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
/**
|
|
734
|
-
* 判断值是否为空
|
|
735
|
-
*/
|
|
736
|
-
private isEmpty(value: any): boolean {
|
|
737
|
-
return value === undefined || value === null || value === '';
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
/**
|
|
741
|
-
* 判断是否为 JSON 字符串
|
|
742
|
-
*/
|
|
743
|
-
private isJSONString(str: string): boolean {
|
|
744
|
-
try {
|
|
745
|
-
JSON.parse(str);
|
|
746
|
-
return true;
|
|
747
|
-
} catch {
|
|
748
|
-
return false;
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
### 注入示例
|
|
755
|
-
|
|
756
|
-
```typescript
|
|
757
|
-
// 假设有以下环境变量:
|
|
758
|
-
VITE_APP_NAME=MyApp
|
|
759
|
-
VITE_FE_API_BASE_URL=https://api.example.com
|
|
760
|
-
VITE_AI_API_TOKEN=sk-xxxxx
|
|
761
|
-
|
|
762
|
-
// AppConfig 初始状态:
|
|
763
|
-
const appConfig = new AppConfig();
|
|
764
|
-
console.log(appConfig.appName); // ''
|
|
765
|
-
console.log(appConfig.feApiBaseUrl); // ''
|
|
766
|
-
console.log(appConfig.aiApiToken); // ''
|
|
767
|
-
|
|
768
|
-
// Bootstrap 初始化后(InjectEnv 插件执行后):
|
|
769
|
-
await bootstrap.initialize();
|
|
770
|
-
|
|
771
|
-
console.log(appConfig.appName); // 'MyApp'
|
|
772
|
-
console.log(appConfig.feApiBaseUrl); // 'https://api.example.com'
|
|
773
|
-
console.log(appConfig.aiApiToken); // 'sk-xxxxx'
|
|
774
|
-
```
|
|
775
|
-
|
|
776
|
-
---
|
|
777
|
-
|
|
778
|
-
## 📦 AppConfig 使用
|
|
779
|
-
|
|
780
|
-
### 1. 在服务中使用(推荐)⭐
|
|
781
|
-
|
|
782
|
-
```typescript
|
|
783
|
-
// src/base/services/UserService.ts
|
|
784
|
-
import { injectable, inject } from 'inversify';
|
|
785
|
-
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
786
|
-
import type { AppConfig } from '@/base/cases/AppConfig';
|
|
787
|
-
|
|
788
|
-
@injectable()
|
|
789
|
-
export class UserService {
|
|
790
|
-
constructor(
|
|
791
|
-
@inject(IOCIdentifier.AppConfig) private config: AppConfig,
|
|
792
|
-
@inject(UserApi) private api: UserApi
|
|
793
|
-
) {}
|
|
794
|
-
|
|
795
|
-
async login(username: string, password: string) {
|
|
796
|
-
// ✅ 使用配置中的 API 地址
|
|
797
|
-
const response = await this.api.post(
|
|
798
|
-
`${this.config.userApiBaseUrl}/login`,
|
|
799
|
-
{ username, password }
|
|
800
|
-
);
|
|
801
|
-
|
|
802
|
-
// ✅ 使用配置中的存储键
|
|
803
|
-
this.storage.setItem(this.config.userTokenStorageKey, response.token);
|
|
804
|
-
|
|
805
|
-
return response.user;
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
```
|
|
809
|
-
|
|
810
|
-
### 2. 在 UI 组件中使用
|
|
811
|
-
|
|
812
|
-
```typescript
|
|
813
|
-
// src/pages/base/HomePage.tsx
|
|
814
|
-
import { useIOC } from '@/uikit/hooks/useIOC';
|
|
815
|
-
|
|
816
|
-
function HomePage() {
|
|
817
|
-
// ✅ 通过 Hook 获取配置
|
|
818
|
-
const config = useIOC('AppConfig');
|
|
819
|
-
|
|
820
|
-
return (
|
|
821
|
-
<div>
|
|
822
|
-
<h1>{config.appName}</h1>
|
|
823
|
-
<p>Version: {config.appVersion}</p>
|
|
824
|
-
<p>Environment: {config.env}</p>
|
|
825
|
-
{!config.isProduction && <p>🚧 Development Mode</p>}
|
|
826
|
-
</div>
|
|
827
|
-
);
|
|
828
|
-
}
|
|
829
|
-
```
|
|
830
|
-
|
|
831
|
-
### 3. 在插件中使用
|
|
832
|
-
|
|
833
|
-
```typescript
|
|
834
|
-
// src/base/apis/feApi/FeApiBootstrap.ts
|
|
835
|
-
export class FeApiBootstarp implements BootstrapExecutorPlugin {
|
|
836
|
-
readonly pluginName = 'FeApiBootstarp';
|
|
837
|
-
|
|
838
|
-
onBefore({ parameters: { ioc } }: BootstrapContext): void {
|
|
839
|
-
const feApi = ioc.get<FeApi>(FeApi);
|
|
840
|
-
// ✅ 从 IOC 获取配置
|
|
841
|
-
const config = ioc.get<AppConfig>(IOCIdentifier.AppConfig);
|
|
842
|
-
|
|
843
|
-
// ✅ 使用配置设置 API 基础 URL
|
|
844
|
-
feApi.setBaseURL(config.feApiBaseUrl);
|
|
845
|
-
|
|
846
|
-
// 添加其他插件
|
|
847
|
-
feApi.usePlugin(
|
|
848
|
-
new AuthTokenPlugin({
|
|
849
|
-
getToken: () => {
|
|
850
|
-
const storage = ioc.get(IOCIdentifier.LocalStorageEncrypt);
|
|
851
|
-
return storage.getItem(config.userTokenStorageKey);
|
|
852
|
-
}
|
|
853
|
-
})
|
|
854
|
-
);
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
```
|
|
858
|
-
|
|
859
|
-
### 4. 直接在代码中使用环境变量
|
|
860
|
-
|
|
861
|
-
```typescript
|
|
862
|
-
// 注意:直接使用 import.meta.env 不推荐,因为无法被 IOC 管理
|
|
863
|
-
|
|
864
|
-
// ❌ 不推荐:直接使用(绕过了 AppConfig)
|
|
865
|
-
function MyComponent() {
|
|
866
|
-
const apiUrl = import.meta.env.VITE_FE_API_BASE_URL;
|
|
867
|
-
// ...
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
// ✅ 推荐:通过 AppConfig 使用
|
|
871
|
-
function MyComponent() {
|
|
872
|
-
const config = useIOC('AppConfig');
|
|
873
|
-
const apiUrl = config.feApiBaseUrl;
|
|
874
|
-
// ...
|
|
875
|
-
}
|
|
876
|
-
```
|
|
877
|
-
|
|
878
|
-
---
|
|
879
|
-
|
|
880
|
-
## 🚀 高级用法
|
|
881
|
-
|
|
882
|
-
### 1. 动态修改配置
|
|
883
|
-
|
|
884
|
-
有时候你可能需要在运行时动态修改配置(而不是通过环境变量):
|
|
885
|
-
|
|
886
|
-
```typescript
|
|
887
|
-
// ✅ 方法 1:在 Bootstrap 初始化前修改
|
|
888
|
-
const appConfig = new AppConfig();
|
|
889
|
-
|
|
890
|
-
// 动态修改配置
|
|
891
|
-
if (window.location.hostname.includes('localhost')) {
|
|
892
|
-
// 本地开发时使用不同的 API 地址
|
|
893
|
-
(appConfig as any).feApiBaseUrl = 'http://localhost:3000/api';
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
// 然后传递给 Bootstrap
|
|
897
|
-
const bootstrap = new Bootstrap({
|
|
898
|
-
envOptions: {
|
|
899
|
-
target: appConfig, // 使用修改后的配置
|
|
900
|
-
source: import.meta.env,
|
|
901
|
-
prefix: 'VITE_',
|
|
902
|
-
blackList: envBlackList
|
|
903
|
-
}
|
|
904
|
-
});
|
|
905
|
-
|
|
906
|
-
await bootstrap.initialize();
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
```typescript
|
|
910
|
-
// ✅ 方法 2:创建配置工厂函数
|
|
911
|
-
export function createAppConfig(): AppConfig {
|
|
912
|
-
const config = new AppConfig();
|
|
913
|
-
|
|
914
|
-
// 根据特定条件动态设置配置
|
|
915
|
-
if (someCondition) {
|
|
916
|
-
(config as any).aiApiBaseUrl = 'https://custom-api.com';
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
return config;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
// 在 Bootstrap 中使用
|
|
923
|
-
const appConfig = createAppConfig();
|
|
924
|
-
```
|
|
925
|
-
|
|
926
|
-
### 2. 配置验证
|
|
927
|
-
|
|
928
|
-
```typescript
|
|
929
|
-
// src/base/cases/AppConfig.ts
|
|
930
|
-
export class AppConfig implements EnvConfigInterface {
|
|
931
|
-
// ... 属性定义
|
|
932
|
-
|
|
933
|
-
/**
|
|
934
|
-
* 验证必需的配置项
|
|
935
|
-
*/
|
|
936
|
-
validate(): void {
|
|
937
|
-
const required: (keyof AppConfig)[] = [
|
|
938
|
-
'appName',
|
|
939
|
-
'feApiBaseUrl',
|
|
940
|
-
'userTokenStorageKey'
|
|
941
|
-
];
|
|
942
|
-
|
|
943
|
-
for (const key of required) {
|
|
944
|
-
if (!this[key]) {
|
|
945
|
-
throw new Error(`Missing required configuration: ${key}`);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
// 在 Bootstrap 中使用
|
|
952
|
-
const appConfig = new AppConfig();
|
|
953
|
-
|
|
954
|
-
await bootstrap.initialize();
|
|
955
|
-
|
|
956
|
-
// 初始化后验证
|
|
957
|
-
appConfig.validate();
|
|
958
|
-
```
|
|
959
|
-
|
|
960
|
-
### 3. 配置组合
|
|
961
|
-
|
|
962
|
-
```typescript
|
|
963
|
-
// ✅ 方法 3:从多个源组合配置
|
|
964
|
-
const appConfig = new AppConfig();
|
|
965
|
-
|
|
966
|
-
const bootstrap = new Bootstrap({
|
|
967
|
-
envOptions: {
|
|
968
|
-
target: appConfig,
|
|
969
|
-
// 合并多个配置源
|
|
970
|
-
source: Object.assign(
|
|
971
|
-
{},
|
|
972
|
-
import.meta.env, // Vite 环境变量
|
|
973
|
-
{ VITE_BOOT_HREF: window.location.href }, // 运行时信息
|
|
974
|
-
window.__APP_CONFIG__ // 服务端注入的配置
|
|
975
|
-
),
|
|
976
|
-
prefix: 'VITE_',
|
|
977
|
-
blackList: envBlackList
|
|
978
|
-
}
|
|
979
|
-
});
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
### 4. 条件配置
|
|
983
|
-
|
|
984
|
-
```typescript
|
|
985
|
-
// src/core/bootstraps/BootstrapClient.ts
|
|
986
|
-
const appConfig = new AppConfig();
|
|
987
|
-
|
|
988
|
-
// ✅ 根据环境设置不同的配置源
|
|
989
|
-
const configSource =
|
|
990
|
-
import.meta.env.VITE_USER_NODE_ENV === 'production'
|
|
991
|
-
? import.meta.env // 生产环境:只使用环境变量
|
|
992
|
-
: {
|
|
993
|
-
...import.meta.env,
|
|
994
|
-
...window.__DEV_CONFIG__ // 开发环境:允许 window 注入
|
|
995
|
-
};
|
|
996
|
-
|
|
997
|
-
const bootstrap = new Bootstrap({
|
|
998
|
-
envOptions: {
|
|
999
|
-
target: appConfig,
|
|
1000
|
-
source: configSource,
|
|
1001
|
-
prefix: 'VITE_',
|
|
1002
|
-
blackList: envBlackList
|
|
1003
|
-
}
|
|
1004
|
-
});
|
|
1005
|
-
```
|
|
1006
|
-
|
|
1007
|
-
---
|
|
1008
|
-
|
|
1009
|
-
## 🧪 测试配置
|
|
1010
|
-
|
|
1011
|
-
### 1. 测试时 Mock AppConfig
|
|
1012
|
-
|
|
1013
|
-
```typescript
|
|
1014
|
-
// __tests__/src/base/services/UserService.test.ts
|
|
1015
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
1016
|
-
import { UserService } from '@/base/services/UserService';
|
|
1017
|
-
import type { AppConfig } from '@/base/cases/AppConfig';
|
|
1018
|
-
|
|
1019
|
-
describe('UserService', () => {
|
|
1020
|
-
let userService: UserService;
|
|
1021
|
-
let mockConfig: AppConfig;
|
|
1022
|
-
|
|
1023
|
-
beforeEach(() => {
|
|
1024
|
-
// ✅ 创建 mock 配置
|
|
1025
|
-
mockConfig = {
|
|
1026
|
-
userApiBaseUrl: 'http://localhost:3000/api',
|
|
1027
|
-
userTokenStorageKey: '__test_token__',
|
|
1028
|
-
userInfoStorageKey: '__test_user__',
|
|
1029
|
-
isProduction: false
|
|
1030
|
-
} as AppConfig;
|
|
1031
|
-
|
|
1032
|
-
// 创建服务
|
|
1033
|
-
userService = new UserService(mockConfig, mockApi, mockStorage);
|
|
1034
|
-
});
|
|
1035
|
-
|
|
1036
|
-
it('should use config values', async () => {
|
|
1037
|
-
await userService.login('user', 'pass');
|
|
1038
|
-
|
|
1039
|
-
// ✅ 验证使用了配置中的值
|
|
1040
|
-
expect(mockApi.post).toHaveBeenCalledWith(
|
|
1041
|
-
`${mockConfig.userApiBaseUrl}/login`,
|
|
1042
|
-
expect.any(Object)
|
|
1043
|
-
);
|
|
1044
|
-
});
|
|
1045
|
-
});
|
|
1046
|
-
```
|
|
1047
|
-
|
|
1048
|
-
### 2. 测试不同环境配置
|
|
1049
|
-
|
|
1050
|
-
```typescript
|
|
1051
|
-
// __tests__/src/base/cases/AppConfig.test.ts
|
|
1052
|
-
import { describe, it, expect } from 'vitest';
|
|
1053
|
-
import { AppConfig } from '@/base/cases/AppConfig';
|
|
1054
|
-
|
|
1055
|
-
describe('AppConfig', () => {
|
|
1056
|
-
it('should detect production environment', () => {
|
|
1057
|
-
const config = new AppConfig('production');
|
|
1058
|
-
expect(config.isProduction).toBe(true);
|
|
1059
|
-
});
|
|
1060
|
-
|
|
1061
|
-
it('should detect non-production environment', () => {
|
|
1062
|
-
const config = new AppConfig('localhost');
|
|
1063
|
-
expect(config.isProduction).toBe(false);
|
|
1064
|
-
});
|
|
1065
|
-
|
|
1066
|
-
it('should have default values', () => {
|
|
1067
|
-
const config = new AppConfig();
|
|
1068
|
-
expect(config.appName).toBe('');
|
|
1069
|
-
expect(config.userTokenStorageKey).toBe('__fe_user_token__');
|
|
1070
|
-
});
|
|
1071
|
-
});
|
|
1072
|
-
```
|
|
1073
|
-
|
|
1074
|
-
### 3. 测试环境变量注入
|
|
1075
|
-
|
|
1076
|
-
```typescript
|
|
1077
|
-
// __tests__/src/core/bootstraps/BootstrapClient.test.ts
|
|
1078
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
1079
|
-
import { BootstrapClient } from '@/core/bootstraps/BootstrapClient';
|
|
1080
|
-
|
|
1081
|
-
describe('BootstrapClient', () => {
|
|
1082
|
-
it('should inject environment variables to AppConfig', async () => {
|
|
1083
|
-
const mockArgs = {
|
|
1084
|
-
root: {},
|
|
1085
|
-
bootHref: 'http://localhost:3000',
|
|
1086
|
-
ioc: {
|
|
1087
|
-
create: vi.fn().mockReturnValue(mockIOC)
|
|
1088
|
-
}
|
|
1089
|
-
};
|
|
1090
|
-
|
|
1091
|
-
// 执行启动
|
|
1092
|
-
await BootstrapClient.main(mockArgs);
|
|
1093
|
-
|
|
1094
|
-
// ✅ 验证配置已注入
|
|
1095
|
-
const globals = (mockArgs.root as any).feGlobals;
|
|
1096
|
-
expect(globals.appConfig).toBeDefined();
|
|
1097
|
-
expect(globals.appConfig.appName).toBeTruthy();
|
|
1098
|
-
});
|
|
1099
|
-
});
|
|
1100
|
-
```
|
|
1101
|
-
|
|
1102
|
-
---
|
|
1103
|
-
|
|
1104
|
-
## 💎 最佳实践
|
|
1105
|
-
|
|
1106
|
-
### 1. ✅ 使用环境变量前缀
|
|
1107
|
-
|
|
1108
|
-
```bash
|
|
1109
|
-
# ✅ 好的命名:使用 VITE_ 前缀
|
|
1110
|
-
VITE_APP_NAME=MyApp
|
|
1111
|
-
VITE_API_BASE_URL=https://api.example.com
|
|
1112
|
-
|
|
1113
|
-
# ❌ 错误命名:没有前缀
|
|
1114
|
-
APP_NAME=MyApp
|
|
1115
|
-
API_BASE_URL=https://api.example.com
|
|
1116
|
-
```
|
|
1117
|
-
|
|
1118
|
-
### 2. ✅ 敏感信息使用 .env.local
|
|
1119
|
-
|
|
1120
|
-
```bash
|
|
1121
|
-
# .env.local(不提交到 git)
|
|
1122
|
-
VITE_AI_API_TOKEN=sk-your-secret-key
|
|
1123
|
-
VITE_DATABASE_PASSWORD=your-password
|
|
1124
|
-
|
|
1125
|
-
# .gitignore
|
|
1126
|
-
.env.local
|
|
1127
|
-
```
|
|
1128
|
-
|
|
1129
|
-
### 3. ✅ 提供 .env.template
|
|
1130
|
-
|
|
1131
|
-
```bash
|
|
1132
|
-
# .env.template(提交到 git)
|
|
1133
|
-
# 团队成员可以复制此文件为 .env.local 并填写实际值
|
|
1134
|
-
|
|
1135
|
-
VITE_AI_API_TOKEN=your-api-token-here
|
|
1136
|
-
VITE_DATABASE_PASSWORD=your-password-here
|
|
1137
|
-
```
|
|
1138
|
-
|
|
1139
|
-
### 4. ✅ 使用类型安全的配置
|
|
1140
|
-
|
|
1141
|
-
```typescript
|
|
1142
|
-
// ✅ 好的做法:通过 AppConfig 访问
|
|
1143
|
-
const config = useIOC('AppConfig');
|
|
1144
|
-
const apiUrl = config.feApiBaseUrl; // ✅ 类型安全
|
|
1145
|
-
|
|
1146
|
-
// ❌ 不好的做法:直接访问环境变量
|
|
1147
|
-
const apiUrl = import.meta.env.VITE_FE_API_BASE_URL; // ❌ 可能为 undefined
|
|
1148
|
-
```
|
|
1149
|
-
|
|
1150
|
-
### 5. ✅ 为 AppConfig 添加注释
|
|
1151
|
-
|
|
1152
|
-
```typescript
|
|
1153
|
-
export class AppConfig {
|
|
1154
|
-
/**
|
|
1155
|
-
* AI API 基础 URL
|
|
1156
|
-
* @description 从 VITE_AI_API_BASE_URL 环境变量注入
|
|
1157
|
-
* @default 'https://api.openai.com/v1'
|
|
1158
|
-
* @example 'https://api.openai.com/v1'
|
|
1159
|
-
*/
|
|
1160
|
-
readonly aiApiBaseUrl = 'https://api.openai.com/v1';
|
|
1161
|
-
}
|
|
1162
|
-
```
|
|
1163
|
-
|
|
1164
|
-
### 6. ✅ 避免在代码中判断环境
|
|
1165
|
-
|
|
1166
|
-
```typescript
|
|
1167
|
-
// ❌ 不好:在代码中判断环境
|
|
1168
|
-
if (process.env.NODE_ENV === 'production') {
|
|
1169
|
-
apiUrl = 'https://api.production.com';
|
|
1170
|
-
} else {
|
|
1171
|
-
apiUrl = 'http://localhost:3000';
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
// ✅ 好:通过配置管理
|
|
1175
|
-
const config = useIOC('AppConfig');
|
|
1176
|
-
const apiUrl = config.feApiBaseUrl; // 自动根据环境使用正确的值
|
|
1177
|
-
```
|
|
1178
|
-
|
|
1179
|
-
### 7. ✅ 配置命名规范
|
|
1180
|
-
|
|
1181
|
-
```bash
|
|
1182
|
-
# ✅ 好的命名:清晰、具体
|
|
1183
|
-
VITE_FE_API_BASE_URL=https://api.example.com
|
|
1184
|
-
VITE_USER_TOKEN_STORAGE_KEY=__fe_user_token__
|
|
1185
|
-
VITE_AI_API_REQUIRE_TOKEN=true
|
|
1186
|
-
|
|
1187
|
-
# ❌ 不好的命名:模糊、简写
|
|
1188
|
-
VITE_API=https://api.example.com
|
|
1189
|
-
VITE_KEY=__token__
|
|
1190
|
-
VITE_REQ=true
|
|
1191
|
-
```
|
|
1192
|
-
|
|
1193
|
-
---
|
|
1194
|
-
|
|
1195
|
-
## ❓ 常见问题
|
|
1196
|
-
|
|
1197
|
-
### Q1: 为什么我的环境变量没有注入?
|
|
1198
|
-
|
|
1199
|
-
**A:** 检查以下几点:
|
|
1200
|
-
|
|
1201
|
-
1. **环境变量前缀**
|
|
1202
|
-
|
|
1203
|
-
```bash
|
|
1204
|
-
# ✅ 正确:使用 VITE_ 前缀
|
|
1205
|
-
VITE_APP_NAME=MyApp
|
|
1206
|
-
|
|
1207
|
-
# ❌ 错误:没有前缀
|
|
1208
|
-
APP_NAME=MyApp
|
|
1209
|
-
```
|
|
1210
|
-
|
|
1211
|
-
2. **AppConfig 属性名**
|
|
1212
|
-
|
|
1213
|
-
```typescript
|
|
1214
|
-
// ✅ 正确:属性名存在
|
|
1215
|
-
export class AppConfig {
|
|
1216
|
-
readonly appName = ''; // ← VITE_APP_NAME 会注入这里
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
// ❌ 错误:没有对应的属性
|
|
1220
|
-
export class AppConfig {
|
|
1221
|
-
// 没有 appName 属性,VITE_APP_NAME 不会被注入
|
|
1222
|
-
}
|
|
1223
|
-
```
|
|
1224
|
-
|
|
1225
|
-
3. **黑名单配置**
|
|
1226
|
-
|
|
1227
|
-
```typescript
|
|
1228
|
-
// config/common.ts
|
|
1229
|
-
export const envBlackList = ['env', 'userNodeEnv'];
|
|
1230
|
-
// 确保你的属性不在黑名单中
|
|
1231
|
-
```
|
|
1232
|
-
|
|
1233
|
-
### Q2: 如何在不同环境使用不同配置?
|
|
1234
|
-
|
|
1235
|
-
**A:** 使用 `--mode` 参数:
|
|
1236
|
-
|
|
1237
|
-
```json
|
|
1238
|
-
{
|
|
1239
|
-
"scripts": {
|
|
1240
|
-
"dev": "vite --mode localhost", // 加载 .env.localhost
|
|
1241
|
-
"dev:staging": "vite --mode staging", // 加载 .env.staging
|
|
1242
|
-
"build:prod": "vite build --mode production" // 加载 .env.production
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
```
|
|
1246
|
-
|
|
1247
|
-
### Q3: 如何处理敏感信息?
|
|
1248
|
-
|
|
1249
|
-
**A:** 使用 `.env.local`:
|
|
1250
|
-
|
|
1251
|
-
```bash
|
|
1252
|
-
# .env.local(不提交到 git)
|
|
1253
|
-
VITE_AI_API_TOKEN=sk-your-secret-key
|
|
1254
|
-
|
|
1255
|
-
# .gitignore
|
|
1256
|
-
.env.local
|
|
1257
|
-
```
|
|
1258
|
-
|
|
1259
|
-
### Q4: 能否在运行时动态修改配置?
|
|
1260
|
-
|
|
1261
|
-
**A:** 可以,但需要在 Bootstrap 初始化前:
|
|
1262
|
-
|
|
1263
|
-
```typescript
|
|
1264
|
-
const appConfig = new AppConfig();
|
|
1265
|
-
|
|
1266
|
-
// ✅ 在 Bootstrap 初始化前修改
|
|
1267
|
-
(appConfig as any).feApiBaseUrl = 'https://custom-api.com';
|
|
1268
|
-
|
|
1269
|
-
const bootstrap = new Bootstrap({
|
|
1270
|
-
envOptions: {
|
|
1271
|
-
target: appConfig, // 使用修改后的配置
|
|
1272
|
-
source: import.meta.env,
|
|
1273
|
-
prefix: 'VITE_',
|
|
1274
|
-
blackList: envBlackList
|
|
1275
|
-
}
|
|
1276
|
-
});
|
|
1277
|
-
|
|
1278
|
-
await bootstrap.initialize();
|
|
1279
|
-
```
|
|
1280
|
-
|
|
1281
|
-
### Q5: 为什么推荐通过 AppConfig 而不是直接使用 import.meta.env?
|
|
1282
|
-
|
|
1283
|
-
**A:**
|
|
1284
|
-
|
|
1285
|
-
| 特性 | import.meta.env | AppConfig |
|
|
1286
|
-
| -------------- | ------------------- | --------------- |
|
|
1287
|
-
| **类型安全** | ❌ 可能为 undefined | ✅ 完整类型定义 |
|
|
1288
|
-
| **默认值** | ❌ 没有 | ✅ 有默认值 |
|
|
1289
|
-
| **可测试性** | ❌ 难以 mock | ✅ 易于 mock |
|
|
1290
|
-
| **集中管理** | ❌ 分散各处 | ✅ 统一管理 |
|
|
1291
|
-
| **运行时修改** | ❌ 不可能 | ✅ 可以 |
|
|
1292
|
-
|
|
1293
|
-
### Q6: 环境变量和配置文件有什么区别?
|
|
1294
|
-
|
|
1295
|
-
**A:**
|
|
1296
|
-
|
|
1297
|
-
**环境变量:** 适用于:
|
|
1298
|
-
|
|
1299
|
-
- 不同环境的配置(API 地址、Token 等)
|
|
1300
|
-
- 敏感信息
|
|
1301
|
-
- 部署时需要修改的配置
|
|
1302
|
-
|
|
1303
|
-
**配置文件(config/):** 适用于:
|
|
1304
|
-
|
|
1305
|
-
- 应用逻辑配置(路由、主题、i18n 等)
|
|
1306
|
-
- 不随环境变化的配置
|
|
1307
|
-
- 代码级的配置
|
|
1308
|
-
|
|
1309
|
-
---
|
|
1310
|
-
|
|
1311
|
-
## 📚 相关文档
|
|
1312
|
-
|
|
1313
|
-
- [项目架构设计](./index.md) - 了解整体架构
|
|
1314
|
-
- [Bootstrap 启动器](./bootstrap.md) - Bootstrap 详解
|
|
1315
|
-
- [IOC 容器](./ioc.md) - 依赖注入详解
|
|
1316
|
-
- [全局变量封装](./global.md) - 浏览器 API 封装
|
|
1317
|
-
|
|
1318
|
-
---
|
|
1319
|
-
|
|
1320
|
-
## 🎉 总结
|
|
1321
|
-
|
|
1322
|
-
环境变量管理系统通过 **Bootstrap + AppConfig + IOC** 的组合,提供了:
|
|
1323
|
-
|
|
1324
|
-
1. **环境隔离** 🌍 - 不同环境使用不同配置,无需修改代码
|
|
1325
|
-
2. **类型安全** 🔒 - 通过 TypeScript 提供完整的类型检查
|
|
1326
|
-
3. **集中管理** 📦 - 所有配置在 AppConfig 中统一管理
|
|
1327
|
-
4. **自动注入** ⚡ - Bootstrap 自动将环境变量注入到 AppConfig
|
|
1328
|
-
5. **易于测试** 🧪 - 可以轻松 mock AppConfig 进行测试
|
|
1329
|
-
6. **灵活扩展** 🚀 - 支持多种配置源和动态修改
|
|
1330
|
-
|
|
1331
|
-
通过合理使用环境变量管理,你可以构建一个更加健壮、灵活、易于维护的应用架构。
|
|
1332
|
-
|
|
1333
|
-
---
|
|
1334
|
-
|
|
1335
|
-
**问题反馈:**
|
|
1336
|
-
如果你对环境变量管理有任何疑问或建议,请在团队频道中讨论或提交 Issue。
|