@qlover/create-app 1.0.2 → 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 +43 -0
- package/dist/index.cjs +9 -9
- package/dist/index.js +9 -9
- package/package.json +4 -3
- 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 -51
- 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
|
-
# Environment Variable Management
|
|
2
|
-
|
|
3
|
-
## 📋 Table of Contents
|
|
4
|
-
|
|
5
|
-
- [What is Environment Variable Management](#-what-is-environment-variable-management)
|
|
6
|
-
- [Why Environment Variables are Needed](#-why-environment-variables-are-needed)
|
|
7
|
-
- [How It Works](#-how-it-works)
|
|
8
|
-
- [Implementation in the Project](#-implementation-in-the-project)
|
|
9
|
-
- [Multi-Environment Configuration](#-multi-environment-configuration)
|
|
10
|
-
- [Environment Variable Injection](#-environment-variable-injection)
|
|
11
|
-
- [AppConfig Usage](#-appconfig-usage)
|
|
12
|
-
- [Advanced Usage](#-advanced-usage)
|
|
13
|
-
- [Testing Configuration](#-testing-configuration)
|
|
14
|
-
- [Best Practices](#-best-practices)
|
|
15
|
-
- [FAQ](#-faq)
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## 🎯 What is Environment Variable Management
|
|
20
|
-
|
|
21
|
-
Environment variable management is a core component of the Bootstrap architecture, responsible for using different configurations in different environments (development, testing, production) and passing configurations to the application through **automatic injection**.
|
|
22
|
-
|
|
23
|
-
### Core Workflow
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
Start App → Vite loads .env files → Bootstrap initializes → Inject env vars to AppConfig → IOC container → App uses them
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### Key Concepts
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
┌─────────────────────────────────────────────────┐
|
|
33
|
-
│ Environment Variable Management System │
|
|
34
|
-
│ ┌───────────────────────────────────────────┐ │
|
|
35
|
-
│ │ 1. Vite --mode selects environment │ │
|
|
36
|
-
│ │ 2. Load corresponding .env file │ │
|
|
37
|
-
│ │ 3. envConfig plugin preprocessing │ │
|
|
38
|
-
│ │ 4. Bootstrap injects to AppConfig │ │
|
|
39
|
-
│ │ 5. Register to IOC container │ │
|
|
40
|
-
│ │ 6. App gets config through IOC │ │
|
|
41
|
-
│ └───────────────────────────────────────────┘ │
|
|
42
|
-
└─────────────────────────────────────────────────┘
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## 🤔 Why Environment Variables are Needed
|
|
48
|
-
|
|
49
|
-
### Problem: Pain Points of Hard-coded Configuration
|
|
50
|
-
|
|
51
|
-
#### ❌ Traditional Approach: Configuration Scattered Everywhere
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
// ❌ Problem 1: API address hard-coded in code
|
|
55
|
-
function fetchUserInfo() {
|
|
56
|
-
// 😰 Dev and prod API addresses are different, need to change code every time
|
|
57
|
-
return fetch('http://localhost:3000/api/user');
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ❌ Problem 2: Configuration scattered across files
|
|
61
|
-
function saveToken(token: string) {
|
|
62
|
-
// 😰 Storage key hard-coded, difficult to manage uniformly
|
|
63
|
-
localStorage.setItem('user_token', token);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ❌ Problem 3: Sensitive information directly in code
|
|
67
|
-
function callAI(prompt: string) {
|
|
68
|
-
// 😰 API Key directly exposed in code, security risk
|
|
69
|
-
return fetch('https://api.openai.com/v1/chat', {
|
|
70
|
-
headers: {
|
|
71
|
-
Authorization: 'Bearer sk-xxxxxxxxxxxx' // 😰 Dangerous!
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ❌ Problem 4: Difficult to switch environments
|
|
77
|
-
if (window.location.host === 'localhost:3000') {
|
|
78
|
-
// 😰 Need to manually determine environment
|
|
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
|
-
**Problem Summary:**
|
|
88
|
-
|
|
89
|
-
- 😰 **Scattered configuration** - Config spread across multiple files, hard to manage
|
|
90
|
-
- 😰 **Difficult to switch environments** - Need to manually modify code or use complex conditions
|
|
91
|
-
- 😰 **Security risks** - Sensitive info may be committed to code repository
|
|
92
|
-
- 😰 **Hard to test** - Need to mock many hard-coded values when testing
|
|
93
|
-
- 😰 **Team collaboration difficulties** - Each developer may have different local configs
|
|
94
|
-
|
|
95
|
-
#### ✅ Solution: Environment Variables + AppConfig
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
// ✅ 1. Environment variable files (different config for different environments)
|
|
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 manages configuration uniformly
|
|
112
|
-
export class AppConfig {
|
|
113
|
-
readonly feApiBaseUrl = ''; // ← Auto-injected
|
|
114
|
-
readonly aiApiToken = ''; // ← Auto-injected
|
|
115
|
-
readonly userTokenStorageKey = '__fe_user_token__';
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// ✅ 3. Get config through IOC container
|
|
119
|
-
@injectable()
|
|
120
|
-
export class UserService {
|
|
121
|
-
constructor(
|
|
122
|
-
@inject(IOCIdentifier.AppConfig) private config: AppConfig
|
|
123
|
-
) {}
|
|
124
|
-
|
|
125
|
-
async fetchUserInfo() {
|
|
126
|
-
// ✅ Get API address from config, automatically adapts to environment
|
|
127
|
-
return fetch(`${this.config.feApiBaseUrl}/user`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// ✅ 4. Switch environments at runtime (no code changes needed)
|
|
132
|
-
npm run dev # localhost environment
|
|
133
|
-
npm run dev:staging # staging environment
|
|
134
|
-
npm run build:production # production environment
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
**Advantages:**
|
|
138
|
-
|
|
139
|
-
- ✅ **Centralized management** - All config managed uniformly in AppConfig
|
|
140
|
-
- ✅ **Easy environment switching** - Just switch run command
|
|
141
|
-
- ✅ **Secure** - Sensitive info managed through `.env.local`, not committed to repo
|
|
142
|
-
- ✅ **Easy to test** - Can easily mock AppConfig when testing
|
|
143
|
-
- ✅ **Team-friendly** - Each developer can have their own `.env.local`
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
## ⚙️ How It Works
|
|
148
|
-
|
|
149
|
-
### Environment Variable Loading Flow
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
┌────────────────────────────────────────────────────────────┐
|
|
153
|
-
│ 1. package.json: Define startup commands │
|
|
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: Load corresponding .env file based on --mode │
|
|
161
|
-
│ --mode localhost → .env.localhost │
|
|
162
|
-
│ --mode staging → .env.staging │
|
|
163
|
-
│ --mode production → .env.production │
|
|
164
|
-
│ │
|
|
165
|
-
│ Loading priority: .env.local > .env.[mode] > .env │
|
|
166
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
167
|
-
↓
|
|
168
|
-
┌────────────────────────────────────────────────────────────┐
|
|
169
|
-
│ 3. vite.config.ts: envConfig plugin preprocessing │
|
|
170
|
-
│ - Inject APP_NAME, APP_VERSION, etc. │
|
|
171
|
-
│ - Set environment variable prefix (VITE_) │
|
|
172
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
173
|
-
↓
|
|
174
|
-
┌────────────────────────────────────────────────────────────┐
|
|
175
|
-
│ 4. BootstrapClient: Initialize Bootstrap │
|
|
176
|
-
│ envOptions: { │
|
|
177
|
-
│ target: appConfig, // Injection target │
|
|
178
|
-
│ source: import.meta.env, // Env var source │
|
|
179
|
-
│ prefix: 'VITE_', // Prefix │
|
|
180
|
-
│ blackList: ['env', 'userNodeEnv'] // Blacklist │
|
|
181
|
-
│ } │
|
|
182
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
183
|
-
↓
|
|
184
|
-
┌────────────────────────────────────────────────────────────┐
|
|
185
|
-
│ 5. InjectEnv plugin: Auto-inject env vars to 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 container: Register AppConfig │
|
|
193
|
-
│ container.bind(IOCIdentifier.AppConfig).toConstantValue │
|
|
194
|
-
└──────────────────┬─────────────────────────────────────────┘
|
|
195
|
-
↓
|
|
196
|
-
┌────────────────────────────────────────────────────────────┐
|
|
197
|
-
│ 7. App usage: Get config through IOC │
|
|
198
|
-
│ const config = useIOC('AppConfig'); │
|
|
199
|
-
│ console.log(config.feApiBaseUrl); │
|
|
200
|
-
└────────────────────────────────────────────────────────────┘
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### Naming Conversion Rules
|
|
204
|
-
|
|
205
|
-
Environment variable names are automatically converted to AppConfig property names:
|
|
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
|
-
**Conversion Rules:**
|
|
215
|
-
|
|
216
|
-
1. Remove prefix (`VITE_`)
|
|
217
|
-
2. Convert underscore-separated to camelCase
|
|
218
|
-
3. Match property name in AppConfig
|
|
219
|
-
|
|
220
|
-
---
|
|
221
|
-
|
|
222
|
-
## 🛠️ Implementation in the Project
|
|
223
|
-
|
|
224
|
-
### 1. Define Startup Commands
|
|
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
|
-
**Explanation:**
|
|
241
|
-
|
|
242
|
-
- `--mode` parameter determines which `.env` file to load
|
|
243
|
-
- Development environment: use `localhost` mode
|
|
244
|
-
- Staging environment: use `staging` mode
|
|
245
|
-
- Production environment: use `production` mode
|
|
246
|
-
|
|
247
|
-
### 2. Configure 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 plugin: preprocess environment variables
|
|
259
|
-
envConfig({
|
|
260
|
-
envPops: true, // Enable env var processing
|
|
261
|
-
envPrefix, // Env var prefix: 'VITE_'
|
|
262
|
-
records: [
|
|
263
|
-
['APP_NAME', name], // Inject app name
|
|
264
|
-
['APP_VERSION', version] // Inject app version
|
|
265
|
-
]
|
|
266
|
-
})
|
|
267
|
-
// ... other plugins
|
|
268
|
-
],
|
|
269
|
-
envPrefix: envPrefix, // Vite env var prefix
|
|
270
|
-
server: {
|
|
271
|
-
port: Number(process.env.VITE_SERVER_PORT || 3200)
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
**Key Configuration:**
|
|
277
|
-
|
|
278
|
-
- `envConfig` plugin handles preprocessing of environment variables
|
|
279
|
-
- `records` can inject additional variables (like info from package.json)
|
|
280
|
-
- `envPrefix` set to `'VITE_'`, only variables with this prefix are exposed to client
|
|
281
|
-
|
|
282
|
-
### 3. Define Common Configuration
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
// config/common.ts
|
|
286
|
-
export const envPrefix = 'VITE_';
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Bootstrap env var injection blacklist
|
|
290
|
-
* These properties won't be injected from env vars
|
|
291
|
-
*/
|
|
292
|
-
export const envBlackList = ['env', 'userNodeEnv'];
|
|
293
|
-
|
|
294
|
-
export const browserGlobalsName = 'feGlobals';
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
### 4. Define AppConfig
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
// src/base/cases/AppConfig.ts
|
|
301
|
-
import type { EnvConfigInterface } from '@qlover/corekit-bridge';
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Application configuration class
|
|
305
|
-
*
|
|
306
|
-
* All properties will be automatically injected with corresponding env var values during Bootstrap initialization
|
|
307
|
-
*
|
|
308
|
-
* Environment variable naming rules:
|
|
309
|
-
* - Property names are converted to UPPER_SNAKE_CASE
|
|
310
|
-
* - Add VITE_ prefix
|
|
311
|
-
*
|
|
312
|
-
* Examples:
|
|
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
|
-
* Current environment mode
|
|
321
|
-
* @description Automatically set from Vite's MODE
|
|
322
|
-
*/
|
|
323
|
-
readonly env: string = import.meta.env.VITE_USER_NODE_ENV
|
|
324
|
-
) {}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Application name
|
|
328
|
-
* @description Injected from VITE_APP_NAME environment variable
|
|
329
|
-
*/
|
|
330
|
-
readonly appName = '';
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Application version
|
|
334
|
-
* @description Injected from VITE_APP_VERSION environment variable
|
|
335
|
-
*/
|
|
336
|
-
readonly appVersion = '';
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* User token storage key
|
|
340
|
-
* @description Injected from VITE_USER_TOKEN_STORAGE_KEY environment variable
|
|
341
|
-
*/
|
|
342
|
-
readonly userTokenStorageKey = '__fe_user_token__';
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* User info storage key
|
|
346
|
-
* @description Injected from VITE_USER_INFO_STORAGE_KEY environment variable
|
|
347
|
-
*/
|
|
348
|
-
readonly userInfoStorageKey = '__fe_user_info__';
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Frontend API base URL
|
|
352
|
-
* @description Injected from VITE_FE_API_BASE_URL environment variable
|
|
353
|
-
*/
|
|
354
|
-
readonly feApiBaseUrl = '';
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* User API base URL
|
|
358
|
-
* @description Injected from VITE_USER_API_BASE_URL environment variable
|
|
359
|
-
*/
|
|
360
|
-
readonly userApiBaseUrl = '';
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* AI API base URL
|
|
364
|
-
* @description Injected from VITE_AI_API_BASE_URL environment variable
|
|
365
|
-
*/
|
|
366
|
-
readonly aiApiBaseUrl = 'https://api.openai.com/v1';
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* AI API token
|
|
370
|
-
* @description Injected from VITE_AI_API_TOKEN environment variable
|
|
371
|
-
*/
|
|
372
|
-
readonly aiApiToken = '';
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* AI API token prefix
|
|
376
|
-
* @description Injected from VITE_AI_API_TOKEN_PREFIX environment variable
|
|
377
|
-
*/
|
|
378
|
-
readonly aiApiTokenPrefix = 'Bearer';
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Whether AI API token is required
|
|
382
|
-
* @description Injected from VITE_AI_API_REQUIRE_TOKEN environment variable
|
|
383
|
-
*/
|
|
384
|
-
readonly aiApiRequireToken = true;
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Default login username
|
|
388
|
-
* @description Injected from VITE_LOGIN_USER environment variable
|
|
389
|
-
*/
|
|
390
|
-
readonly loginUser = '';
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* Default login password
|
|
394
|
-
* @description Injected from VITE_LOGIN_PASSWORD environment variable
|
|
395
|
-
*/
|
|
396
|
-
readonly loginPassword = '';
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* OpenAI available models list
|
|
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 base URL
|
|
411
|
-
* @description Injected from VITE_OPEN_AI_BASE_URL environment variable
|
|
412
|
-
*/
|
|
413
|
-
readonly openAiBaseUrl = '';
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* OpenAI API token
|
|
417
|
-
* @description Injected from VITE_OPEN_AI_TOKEN environment variable
|
|
418
|
-
*/
|
|
419
|
-
readonly openAiToken = '';
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* OpenAI API token prefix
|
|
423
|
-
* @description Injected from VITE_OPEN_AI_TOKEN_PREFIX environment variable
|
|
424
|
-
*/
|
|
425
|
-
readonly openAiTokenPrefix = '';
|
|
426
|
-
|
|
427
|
-
/**
|
|
428
|
-
* Whether OpenAI API token is required
|
|
429
|
-
* @description Injected from VITE_OPEN_AI_REQUIRE_TOKEN environment variable
|
|
430
|
-
*/
|
|
431
|
-
readonly openAiRequireToken = true;
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Project startup URL
|
|
435
|
-
* @description Injected from Bootstrap's BOOT_HREF
|
|
436
|
-
*/
|
|
437
|
-
readonly bootHref = '';
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Whether is production environment
|
|
441
|
-
*/
|
|
442
|
-
get isProduction(): boolean {
|
|
443
|
-
return this.env === 'production';
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
### 5. Bootstrap Configuration
|
|
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
|
-
// Create IOC container
|
|
462
|
-
const IOC = ioc.create({
|
|
463
|
-
pathname: bootHref,
|
|
464
|
-
appConfig: appConfig
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
// Create Bootstrap instance
|
|
468
|
-
const bootstrap = new Bootstrap({
|
|
469
|
-
root,
|
|
470
|
-
logger,
|
|
471
|
-
ioc: {
|
|
472
|
-
manager: IOC,
|
|
473
|
-
register: iocRegister
|
|
474
|
-
},
|
|
475
|
-
// ✅ Environment variable injection configuration
|
|
476
|
-
envOptions: {
|
|
477
|
-
target: appConfig, // Injection target: AppConfig instance
|
|
478
|
-
source: Object.assign({}, import.meta.env, {
|
|
479
|
-
[envPrefix + 'BOOT_HREF']: bootHref // Additionally inject startup URL
|
|
480
|
-
}),
|
|
481
|
-
prefix: envPrefix, // Env var prefix: 'VITE_'
|
|
482
|
-
blackList: envBlackList // Blacklist: ['env', 'userNodeEnv']
|
|
483
|
-
},
|
|
484
|
-
// Global variable encapsulation configuration
|
|
485
|
-
globalOptions: {
|
|
486
|
-
sources: globals,
|
|
487
|
-
target: browserGlobalsName
|
|
488
|
-
}
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
try {
|
|
492
|
-
logger.info('bootstrap start...');
|
|
493
|
-
|
|
494
|
-
// ✅ Initialize Bootstrap (env var injection executes here)
|
|
495
|
-
await bootstrap.initialize();
|
|
496
|
-
|
|
497
|
-
// Register business plugins
|
|
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
|
-
**Key Flow:**
|
|
512
|
-
|
|
513
|
-
1. `appConfig` is an AppConfig instance with default values for all properties
|
|
514
|
-
2. `bootstrap.initialize()` executes the `InjectEnv` plugin
|
|
515
|
-
3. `InjectEnv` plugin iterates through `appConfig` properties, looking for corresponding env vars in `import.meta.env`
|
|
516
|
-
4. If an env var is found and value is not empty, it overwrites the default value
|
|
517
|
-
5. Finally `appConfig` is registered to the IOC container
|
|
518
|
-
|
|
519
|
-
---
|
|
520
|
-
|
|
521
|
-
## 🌍 Multi-Environment Configuration
|
|
522
|
-
|
|
523
|
-
### Environment File Structure
|
|
524
|
-
|
|
525
|
-
```
|
|
526
|
-
Project root/
|
|
527
|
-
├── .env # Default config (shared across all environments)
|
|
528
|
-
├── .env.localhost # Local development environment
|
|
529
|
-
├── .env.staging # Staging environment
|
|
530
|
-
├── .env.production # Production environment
|
|
531
|
-
├── .env.local # Local override config (not committed to git)
|
|
532
|
-
└── .env.template # Env var template (committed to git)
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
### Loading Priority
|
|
536
|
-
|
|
537
|
-
```
|
|
538
|
-
.env.local > .env.[mode] > .env
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
**Example:**
|
|
542
|
-
|
|
543
|
-
```bash
|
|
544
|
-
# Run: npm run dev (vite --mode localhost)
|
|
545
|
-
# Loading order:
|
|
546
|
-
# 1. .env.local # Highest priority
|
|
547
|
-
# 2. .env.localhost # Second
|
|
548
|
-
# 3. .env # Last
|
|
549
|
-
|
|
550
|
-
# Run: npm run build:production (vite build --mode production)
|
|
551
|
-
# Loading order:
|
|
552
|
-
# 1. .env.local
|
|
553
|
-
# 2. .env.production
|
|
554
|
-
# 3. .env
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
### Example 1: Default Configuration
|
|
558
|
-
|
|
559
|
-
```bash
|
|
560
|
-
# .env
|
|
561
|
-
# Configuration shared across all environments
|
|
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
|
-
### Example 2: Local Development Environment
|
|
571
|
-
|
|
572
|
-
```bash
|
|
573
|
-
# .env.localhost
|
|
574
|
-
# Local development environment config
|
|
575
|
-
|
|
576
|
-
# API configuration
|
|
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 configuration (dev environment may use local Mock)
|
|
582
|
-
VITE_AI_API_TOKEN=sk-dev-xxxxx
|
|
583
|
-
VITE_AI_API_REQUIRE_TOKEN=false
|
|
584
|
-
|
|
585
|
-
# Debug configuration
|
|
586
|
-
VITE_LOG_LEVEL=debug
|
|
587
|
-
VITE_DEBUG=true
|
|
588
|
-
|
|
589
|
-
# Default login info (convenient for development)
|
|
590
|
-
VITE_LOGIN_USER=admin
|
|
591
|
-
VITE_LOGIN_PASSWORD=admin123
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
### Example 3: Staging Environment
|
|
595
|
-
|
|
596
|
-
```bash
|
|
597
|
-
# .env.staging
|
|
598
|
-
# Staging environment config
|
|
599
|
-
|
|
600
|
-
# API configuration
|
|
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 configuration
|
|
606
|
-
VITE_AI_API_TOKEN=sk-staging-xxxxx
|
|
607
|
-
VITE_AI_API_REQUIRE_TOKEN=true
|
|
608
|
-
|
|
609
|
-
# Debug configuration
|
|
610
|
-
VITE_LOG_LEVEL=info
|
|
611
|
-
VITE_DEBUG=true
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
### Example 4: Production Environment
|
|
615
|
-
|
|
616
|
-
```bash
|
|
617
|
-
# .env.production
|
|
618
|
-
# Production environment config
|
|
619
|
-
|
|
620
|
-
# API configuration
|
|
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 configuration
|
|
626
|
-
VITE_AI_API_TOKEN=sk-prod-xxxxx
|
|
627
|
-
VITE_AI_API_REQUIRE_TOKEN=true
|
|
628
|
-
|
|
629
|
-
# Debug configuration
|
|
630
|
-
VITE_LOG_LEVEL=error
|
|
631
|
-
VITE_DEBUG=false
|
|
632
|
-
```
|
|
633
|
-
|
|
634
|
-
### Example 5: Local Override Configuration
|
|
635
|
-
|
|
636
|
-
```bash
|
|
637
|
-
# .env.local
|
|
638
|
-
# Local personal config, not committed to git
|
|
639
|
-
|
|
640
|
-
# Override AI API Token (use your own key)
|
|
641
|
-
VITE_AI_API_TOKEN=sk-my-personal-key
|
|
642
|
-
|
|
643
|
-
# Override API address (connect to your local service)
|
|
644
|
-
VITE_FE_API_BASE_URL=http://192.168.1.100:3000/api
|
|
645
|
-
|
|
646
|
-
# Enable specific features
|
|
647
|
-
VITE_ENABLE_EXPERIMENTAL_FEATURES=true
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
### Example 6: Environment Variable Template
|
|
651
|
-
|
|
652
|
-
```bash
|
|
653
|
-
# .env.template
|
|
654
|
-
# Env var template, committed to git for team reference
|
|
655
|
-
|
|
656
|
-
# ===== Required Configuration =====
|
|
657
|
-
VITE_FE_API_BASE_URL=https://your-api-url.com
|
|
658
|
-
VITE_AI_API_TOKEN=your-ai-api-token-here
|
|
659
|
-
|
|
660
|
-
# ===== Optional Configuration =====
|
|
661
|
-
VITE_LOGIN_USER=your-default-username
|
|
662
|
-
VITE_LOGIN_PASSWORD=your-default-password
|
|
663
|
-
|
|
664
|
-
# ===== Instructions =====
|
|
665
|
-
# 1. Copy this file as .env.local
|
|
666
|
-
# 2. Fill in actual configuration values
|
|
667
|
-
# 3. .env.local won't be committed to git
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
---
|
|
671
|
-
|
|
672
|
-
## 🔄 Environment Variable Injection
|
|
673
|
-
|
|
674
|
-
### InjectEnv Plugin Working Principle
|
|
675
|
-
|
|
676
|
-
```typescript
|
|
677
|
-
// @qlover/corekit-bridge/src/core/bootstrap/plugins/InjectEnv.ts (simplified)
|
|
678
|
-
export class InjectEnv implements BootstrapExecutorPlugin {
|
|
679
|
-
readonly pluginName = 'InjectEnv';
|
|
680
|
-
|
|
681
|
-
constructor(protected options: InjectEnvConfig) {}
|
|
682
|
-
|
|
683
|
-
/**
|
|
684
|
-
* Execute before Bootstrap initialization
|
|
685
|
-
*/
|
|
686
|
-
onBefore(): void {
|
|
687
|
-
const { target, source, prefix, blackList } = this.options;
|
|
688
|
-
|
|
689
|
-
// Iterate through all properties of target object
|
|
690
|
-
for (const key in target) {
|
|
691
|
-
// Skip properties in blacklist
|
|
692
|
-
if (blackList.includes(key)) {
|
|
693
|
-
continue;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
const currentValue = target[key as keyof typeof target];
|
|
697
|
-
|
|
698
|
-
// Get corresponding env var value
|
|
699
|
-
const envValue = this.getEnvValue(key, currentValue);
|
|
700
|
-
|
|
701
|
-
// If env var exists and differs from default value, inject it
|
|
702
|
-
if (!this.isEmpty(envValue) && envValue !== currentValue) {
|
|
703
|
-
target[key as keyof typeof target] = envValue;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
/**
|
|
709
|
-
* Get environment variable value
|
|
710
|
-
*/
|
|
711
|
-
private getEnvValue<D>(key: string, defaultValue?: D): D {
|
|
712
|
-
const { prefix = '', source = {} } = this.options;
|
|
713
|
-
|
|
714
|
-
// Convert camelCase to UPPER_SNAKE_CASE
|
|
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
|
-
// Add prefix
|
|
720
|
-
const envKey = `${prefix}${formattedKey}`;
|
|
721
|
-
|
|
722
|
-
// Get env var value
|
|
723
|
-
const value = source[envKey];
|
|
724
|
-
|
|
725
|
-
// If it's a JSON string, parse it
|
|
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
|
-
* Check if value is empty
|
|
735
|
-
*/
|
|
736
|
-
private isEmpty(value: any): boolean {
|
|
737
|
-
return value === undefined || value === null || value === '';
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
/**
|
|
741
|
-
* Check if it's a JSON string
|
|
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
|
-
### Injection Example
|
|
755
|
-
|
|
756
|
-
```typescript
|
|
757
|
-
// Assuming the following environment variables:
|
|
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 initial state:
|
|
763
|
-
const appConfig = new AppConfig();
|
|
764
|
-
console.log(appConfig.appName); // ''
|
|
765
|
-
console.log(appConfig.feApiBaseUrl); // ''
|
|
766
|
-
console.log(appConfig.aiApiToken); // ''
|
|
767
|
-
|
|
768
|
-
// After Bootstrap initialization (after InjectEnv plugin execution):
|
|
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 Usage
|
|
779
|
-
|
|
780
|
-
### 1. Use in Services (Recommended) ⭐
|
|
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
|
-
// ✅ Use API address from config
|
|
797
|
-
const response = await this.api.post(
|
|
798
|
-
`${this.config.userApiBaseUrl}/login`,
|
|
799
|
-
{ username, password }
|
|
800
|
-
);
|
|
801
|
-
|
|
802
|
-
// ✅ Use storage key from config
|
|
803
|
-
this.storage.setItem(this.config.userTokenStorageKey, response.token);
|
|
804
|
-
|
|
805
|
-
return response.user;
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
```
|
|
809
|
-
|
|
810
|
-
### 2. Use in UI Components
|
|
811
|
-
|
|
812
|
-
```typescript
|
|
813
|
-
// src/pages/base/HomePage.tsx
|
|
814
|
-
import { useIOC } from '@/uikit/hooks/useIOC';
|
|
815
|
-
|
|
816
|
-
function HomePage() {
|
|
817
|
-
// ✅ Get config through 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. Use in Plugins
|
|
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
|
-
// ✅ Get config from IOC
|
|
841
|
-
const config = ioc.get<AppConfig>(IOCIdentifier.AppConfig);
|
|
842
|
-
|
|
843
|
-
// ✅ Use config to set API base URL
|
|
844
|
-
feApi.setBaseURL(config.feApiBaseUrl);
|
|
845
|
-
|
|
846
|
-
// Add other plugins
|
|
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. Use Environment Variables Directly in Code
|
|
860
|
-
|
|
861
|
-
```typescript
|
|
862
|
-
// Note: Using import.meta.env directly is not recommended as it can't be managed by IOC
|
|
863
|
-
|
|
864
|
-
// ❌ Not recommended: Direct use (bypasses AppConfig)
|
|
865
|
-
function MyComponent() {
|
|
866
|
-
const apiUrl = import.meta.env.VITE_FE_API_BASE_URL;
|
|
867
|
-
// ...
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
// ✅ Recommended: Use through AppConfig
|
|
871
|
-
function MyComponent() {
|
|
872
|
-
const config = useIOC('AppConfig');
|
|
873
|
-
const apiUrl = config.feApiBaseUrl;
|
|
874
|
-
// ...
|
|
875
|
-
}
|
|
876
|
-
```
|
|
877
|
-
|
|
878
|
-
---
|
|
879
|
-
|
|
880
|
-
## 🚀 Advanced Usage
|
|
881
|
-
|
|
882
|
-
### 1. Dynamically Modify Configuration
|
|
883
|
-
|
|
884
|
-
Sometimes you may need to dynamically modify configuration at runtime (rather than through environment variables):
|
|
885
|
-
|
|
886
|
-
```typescript
|
|
887
|
-
// ✅ Method 1: Modify before Bootstrap initialization
|
|
888
|
-
const appConfig = new AppConfig();
|
|
889
|
-
|
|
890
|
-
// Dynamically modify config
|
|
891
|
-
if (window.location.hostname.includes('localhost')) {
|
|
892
|
-
// Use different API address for local development
|
|
893
|
-
(appConfig as any).feApiBaseUrl = 'http://localhost:3000/api';
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
// Then pass to Bootstrap
|
|
897
|
-
const bootstrap = new Bootstrap({
|
|
898
|
-
envOptions: {
|
|
899
|
-
target: appConfig, // Use modified config
|
|
900
|
-
source: import.meta.env,
|
|
901
|
-
prefix: 'VITE_',
|
|
902
|
-
blackList: envBlackList
|
|
903
|
-
}
|
|
904
|
-
});
|
|
905
|
-
|
|
906
|
-
await bootstrap.initialize();
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
```typescript
|
|
910
|
-
// ✅ Method 2: Create config factory function
|
|
911
|
-
export function createAppConfig(): AppConfig {
|
|
912
|
-
const config = new AppConfig();
|
|
913
|
-
|
|
914
|
-
// Dynamically set config based on specific conditions
|
|
915
|
-
if (someCondition) {
|
|
916
|
-
(config as any).aiApiBaseUrl = 'https://custom-api.com';
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
return config;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
// Use in Bootstrap
|
|
923
|
-
const appConfig = createAppConfig();
|
|
924
|
-
```
|
|
925
|
-
|
|
926
|
-
### 2. Configuration Validation
|
|
927
|
-
|
|
928
|
-
```typescript
|
|
929
|
-
// src/base/cases/AppConfig.ts
|
|
930
|
-
export class AppConfig implements EnvConfigInterface {
|
|
931
|
-
// ... property definitions
|
|
932
|
-
|
|
933
|
-
/**
|
|
934
|
-
* Validate required configuration items
|
|
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
|
-
// Use in Bootstrap
|
|
952
|
-
const appConfig = new AppConfig();
|
|
953
|
-
|
|
954
|
-
await bootstrap.initialize();
|
|
955
|
-
|
|
956
|
-
// Validate after initialization
|
|
957
|
-
appConfig.validate();
|
|
958
|
-
```
|
|
959
|
-
|
|
960
|
-
### 3. Configuration Composition
|
|
961
|
-
|
|
962
|
-
```typescript
|
|
963
|
-
// ✅ Method 3: Compose config from multiple sources
|
|
964
|
-
const appConfig = new AppConfig();
|
|
965
|
-
|
|
966
|
-
const bootstrap = new Bootstrap({
|
|
967
|
-
envOptions: {
|
|
968
|
-
target: appConfig,
|
|
969
|
-
// Merge multiple config sources
|
|
970
|
-
source: Object.assign(
|
|
971
|
-
{},
|
|
972
|
-
import.meta.env, // Vite environment variables
|
|
973
|
-
{ VITE_BOOT_HREF: window.location.href }, // Runtime info
|
|
974
|
-
window.__APP_CONFIG__ // Server-injected config
|
|
975
|
-
),
|
|
976
|
-
prefix: 'VITE_',
|
|
977
|
-
blackList: envBlackList
|
|
978
|
-
}
|
|
979
|
-
});
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
### 4. Conditional Configuration
|
|
983
|
-
|
|
984
|
-
```typescript
|
|
985
|
-
// src/core/bootstraps/BootstrapClient.ts
|
|
986
|
-
const appConfig = new AppConfig();
|
|
987
|
-
|
|
988
|
-
// ✅ Set different config sources based on environment
|
|
989
|
-
const configSource =
|
|
990
|
-
import.meta.env.VITE_USER_NODE_ENV === 'production'
|
|
991
|
-
? import.meta.env // Production: only use env vars
|
|
992
|
-
: {
|
|
993
|
-
...import.meta.env,
|
|
994
|
-
...window.__DEV_CONFIG__ // Development: allow window injection
|
|
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
|
-
## 🧪 Testing Configuration
|
|
1010
|
-
|
|
1011
|
-
### 1. Mock AppConfig in Tests
|
|
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
|
-
// ✅ Create mock config
|
|
1025
|
-
mockConfig = {
|
|
1026
|
-
userApiBaseUrl: 'http://localhost:3000/api',
|
|
1027
|
-
userTokenStorageKey: '__test_token__',
|
|
1028
|
-
userInfoStorageKey: '__test_user__',
|
|
1029
|
-
isProduction: false
|
|
1030
|
-
} as AppConfig;
|
|
1031
|
-
|
|
1032
|
-
// Create service
|
|
1033
|
-
userService = new UserService(mockConfig, mockApi, mockStorage);
|
|
1034
|
-
});
|
|
1035
|
-
|
|
1036
|
-
it('should use config values', async () => {
|
|
1037
|
-
await userService.login('user', 'pass');
|
|
1038
|
-
|
|
1039
|
-
// ✅ Verify config values were used
|
|
1040
|
-
expect(mockApi.post).toHaveBeenCalledWith(
|
|
1041
|
-
`${mockConfig.userApiBaseUrl}/login`,
|
|
1042
|
-
expect.any(Object)
|
|
1043
|
-
);
|
|
1044
|
-
});
|
|
1045
|
-
});
|
|
1046
|
-
```
|
|
1047
|
-
|
|
1048
|
-
### 2. Test Different Environment Configurations
|
|
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. Test Environment Variable Injection
|
|
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
|
-
// Execute startup
|
|
1092
|
-
await BootstrapClient.main(mockArgs);
|
|
1093
|
-
|
|
1094
|
-
// ✅ Verify config was injected
|
|
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
|
-
## 💎 Best Practices
|
|
1105
|
-
|
|
1106
|
-
### 1. ✅ Use Environment Variable Prefix
|
|
1107
|
-
|
|
1108
|
-
```bash
|
|
1109
|
-
# ✅ Good naming: Use VITE_ prefix
|
|
1110
|
-
VITE_APP_NAME=MyApp
|
|
1111
|
-
VITE_API_BASE_URL=https://api.example.com
|
|
1112
|
-
|
|
1113
|
-
# ❌ Wrong naming: No prefix
|
|
1114
|
-
APP_NAME=MyApp
|
|
1115
|
-
API_BASE_URL=https://api.example.com
|
|
1116
|
-
```
|
|
1117
|
-
|
|
1118
|
-
### 2. ✅ Use .env.local for Sensitive Information
|
|
1119
|
-
|
|
1120
|
-
```bash
|
|
1121
|
-
# .env.local (not committed to 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. ✅ Provide .env.template
|
|
1130
|
-
|
|
1131
|
-
```bash
|
|
1132
|
-
# .env.template (committed to git)
|
|
1133
|
-
# Team members can copy this file as .env.local and fill in actual values
|
|
1134
|
-
|
|
1135
|
-
VITE_AI_API_TOKEN=your-api-token-here
|
|
1136
|
-
VITE_DATABASE_PASSWORD=your-password-here
|
|
1137
|
-
```
|
|
1138
|
-
|
|
1139
|
-
### 4. ✅ Use Type-safe Configuration
|
|
1140
|
-
|
|
1141
|
-
```typescript
|
|
1142
|
-
// ✅ Good practice: Access through AppConfig
|
|
1143
|
-
const config = useIOC('AppConfig');
|
|
1144
|
-
const apiUrl = config.feApiBaseUrl; // ✅ Type-safe
|
|
1145
|
-
|
|
1146
|
-
// ❌ Bad practice: Direct access to env vars
|
|
1147
|
-
const apiUrl = import.meta.env.VITE_FE_API_BASE_URL; // ❌ May be undefined
|
|
1148
|
-
```
|
|
1149
|
-
|
|
1150
|
-
### 5. ✅ Add Comments to AppConfig
|
|
1151
|
-
|
|
1152
|
-
```typescript
|
|
1153
|
-
export class AppConfig {
|
|
1154
|
-
/**
|
|
1155
|
-
* AI API base URL
|
|
1156
|
-
* @description Injected from VITE_AI_API_BASE_URL environment variable
|
|
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. ✅ Avoid Environment Checks in Code
|
|
1165
|
-
|
|
1166
|
-
```typescript
|
|
1167
|
-
// ❌ Bad: Check environment in code
|
|
1168
|
-
if (process.env.NODE_ENV === 'production') {
|
|
1169
|
-
apiUrl = 'https://api.production.com';
|
|
1170
|
-
} else {
|
|
1171
|
-
apiUrl = 'http://localhost:3000';
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
// ✅ Good: Manage through config
|
|
1175
|
-
const config = useIOC('AppConfig');
|
|
1176
|
-
const apiUrl = config.feApiBaseUrl; // Automatically uses correct value based on environment
|
|
1177
|
-
```
|
|
1178
|
-
|
|
1179
|
-
### 7. ✅ Configuration Naming Conventions
|
|
1180
|
-
|
|
1181
|
-
```bash
|
|
1182
|
-
# ✅ Good naming: Clear and specific
|
|
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
|
-
# ❌ Bad naming: Vague, abbreviated
|
|
1188
|
-
VITE_API=https://api.example.com
|
|
1189
|
-
VITE_KEY=__token__
|
|
1190
|
-
VITE_REQ=true
|
|
1191
|
-
```
|
|
1192
|
-
|
|
1193
|
-
---
|
|
1194
|
-
|
|
1195
|
-
## ❓ FAQ
|
|
1196
|
-
|
|
1197
|
-
### Q1: Why aren't my environment variables being injected?
|
|
1198
|
-
|
|
1199
|
-
**A:** Check the following points:
|
|
1200
|
-
|
|
1201
|
-
1. **Environment variable prefix**
|
|
1202
|
-
|
|
1203
|
-
```bash
|
|
1204
|
-
# ✅ Correct: Use VITE_ prefix
|
|
1205
|
-
VITE_APP_NAME=MyApp
|
|
1206
|
-
|
|
1207
|
-
# ❌ Wrong: No prefix
|
|
1208
|
-
APP_NAME=MyApp
|
|
1209
|
-
```
|
|
1210
|
-
|
|
1211
|
-
2. **AppConfig property name**
|
|
1212
|
-
|
|
1213
|
-
```typescript
|
|
1214
|
-
// ✅ Correct: Property exists
|
|
1215
|
-
export class AppConfig {
|
|
1216
|
-
readonly appName = ''; // ← VITE_APP_NAME will inject here
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
// ❌ Wrong: No corresponding property
|
|
1220
|
-
export class AppConfig {
|
|
1221
|
-
// No appName property, VITE_APP_NAME won't be injected
|
|
1222
|
-
}
|
|
1223
|
-
```
|
|
1224
|
-
|
|
1225
|
-
3. **Blacklist configuration**
|
|
1226
|
-
|
|
1227
|
-
```typescript
|
|
1228
|
-
// config/common.ts
|
|
1229
|
-
export const envBlackList = ['env', 'userNodeEnv'];
|
|
1230
|
-
// Make sure your property is not in the blacklist
|
|
1231
|
-
```
|
|
1232
|
-
|
|
1233
|
-
### Q2: How to use different configurations in different environments?
|
|
1234
|
-
|
|
1235
|
-
**A:** Use the `--mode` parameter:
|
|
1236
|
-
|
|
1237
|
-
```json
|
|
1238
|
-
{
|
|
1239
|
-
"scripts": {
|
|
1240
|
-
"dev": "vite --mode localhost", // Load .env.localhost
|
|
1241
|
-
"dev:staging": "vite --mode staging", // Load .env.staging
|
|
1242
|
-
"build:prod": "vite build --mode production" // Load .env.production
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
```
|
|
1246
|
-
|
|
1247
|
-
### Q3: How to handle sensitive information?
|
|
1248
|
-
|
|
1249
|
-
**A:** Use `.env.local`:
|
|
1250
|
-
|
|
1251
|
-
```bash
|
|
1252
|
-
# .env.local (not committed to git)
|
|
1253
|
-
VITE_AI_API_TOKEN=sk-your-secret-key
|
|
1254
|
-
|
|
1255
|
-
# .gitignore
|
|
1256
|
-
.env.local
|
|
1257
|
-
```
|
|
1258
|
-
|
|
1259
|
-
### Q4: Can configuration be dynamically modified at runtime?
|
|
1260
|
-
|
|
1261
|
-
**A:** Yes, but it needs to be done before Bootstrap initialization:
|
|
1262
|
-
|
|
1263
|
-
```typescript
|
|
1264
|
-
const appConfig = new AppConfig();
|
|
1265
|
-
|
|
1266
|
-
// ✅ Modify before Bootstrap initialization
|
|
1267
|
-
(appConfig as any).feApiBaseUrl = 'https://custom-api.com';
|
|
1268
|
-
|
|
1269
|
-
const bootstrap = new Bootstrap({
|
|
1270
|
-
envOptions: {
|
|
1271
|
-
target: appConfig, // Use modified config
|
|
1272
|
-
source: import.meta.env,
|
|
1273
|
-
prefix: 'VITE_',
|
|
1274
|
-
blackList: envBlackList
|
|
1275
|
-
}
|
|
1276
|
-
});
|
|
1277
|
-
|
|
1278
|
-
await bootstrap.initialize();
|
|
1279
|
-
```
|
|
1280
|
-
|
|
1281
|
-
### Q5: Why recommend using AppConfig instead of import.meta.env directly?
|
|
1282
|
-
|
|
1283
|
-
**A:**
|
|
1284
|
-
|
|
1285
|
-
| Feature | import.meta.env | AppConfig |
|
|
1286
|
-
| -------------------------- | ------------------- | ---------------------------- |
|
|
1287
|
-
| **Type Safety** | ❌ May be undefined | ✅ Complete type definitions |
|
|
1288
|
-
| **Default Values** | ❌ None | ✅ Has default values |
|
|
1289
|
-
| **Testability** | ❌ Hard to mock | ✅ Easy to mock |
|
|
1290
|
-
| **Centralized Management** | ❌ Scattered | ✅ Unified management |
|
|
1291
|
-
| **Runtime Modification** | ❌ Not possible | ✅ Possible |
|
|
1292
|
-
|
|
1293
|
-
### Q6: What's the difference between environment variables and config files?
|
|
1294
|
-
|
|
1295
|
-
**A:**
|
|
1296
|
-
|
|
1297
|
-
**Environment variables:** Suitable for:
|
|
1298
|
-
|
|
1299
|
-
- Configuration that differs by environment (API addresses, tokens, etc.)
|
|
1300
|
-
- Sensitive information
|
|
1301
|
-
- Configuration that needs to be modified during deployment
|
|
1302
|
-
|
|
1303
|
-
**Config files (config/):** Suitable for:
|
|
1304
|
-
|
|
1305
|
-
- Application logic configuration (routes, themes, i18n, etc.)
|
|
1306
|
-
- Configuration that doesn't change with environment
|
|
1307
|
-
- Code-level configuration
|
|
1308
|
-
|
|
1309
|
-
---
|
|
1310
|
-
|
|
1311
|
-
## 📚 Related Documentation
|
|
1312
|
-
|
|
1313
|
-
- [Project Architecture Design](./index.md) - Understand overall architecture
|
|
1314
|
-
- [Bootstrap Initializer](./bootstrap.md) - Bootstrap details
|
|
1315
|
-
- [IOC Container](./ioc.md) - Dependency injection details
|
|
1316
|
-
- [Global Variable Encapsulation](./global.md) - Browser API encapsulation
|
|
1317
|
-
|
|
1318
|
-
---
|
|
1319
|
-
|
|
1320
|
-
## 🎉 Summary
|
|
1321
|
-
|
|
1322
|
-
The environment variable management system, through the combination of **Bootstrap + AppConfig + IOC**, provides:
|
|
1323
|
-
|
|
1324
|
-
1. **Environment Isolation** 🌍 - Different environments use different configs, no code changes needed
|
|
1325
|
-
2. **Type Safety** 🔒 - Complete type checking through TypeScript
|
|
1326
|
-
3. **Centralized Management** 📦 - All config managed uniformly in AppConfig
|
|
1327
|
-
4. **Auto Injection** ⚡ - Bootstrap automatically injects env vars to AppConfig
|
|
1328
|
-
5. **Easy to Test** 🧪 - Can easily mock AppConfig for testing
|
|
1329
|
-
6. **Flexible Extension** 🚀 - Supports multiple config sources and dynamic modification
|
|
1330
|
-
|
|
1331
|
-
Through proper use of environment variable management, you can build a more robust, flexible, and maintainable application architecture.
|
|
1332
|
-
|
|
1333
|
-
---
|
|
1334
|
-
|
|
1335
|
-
**Feedback:**
|
|
1336
|
-
If you have any questions or suggestions about environment variable management, please discuss in the team channel or submit an Issue.
|