@qlover/create-app 0.4.2 → 0.4.3

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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # @qlover/create-app
2
2
 
3
+ ## 0.4.3
4
+
5
+ ### Patch Changes
6
+
7
+ #### ✨ Features
8
+
9
+ - **create-app:** enhance environment configuration and localization support ([76e5e22](https://github.com/qlover/fe-base/commit/76e5e22e41fe23ce109c303ca3974103f8a85cf6)) ([#432](https://github.com/qlover/fe-base/pull/432))
10
+
11
+ - Updated .gitignore to include .env files and added .env.template to the repository.
12
+ - Introduced a new .env.template file for environment variable configuration in the react-app template.
13
+ - Enhanced package.json scripts for development modes: added staging and production modes.
14
+ - Updated README.md to document environment variable usage with Vite.
15
+ - Added new error identifiers for token handling in Error.ts and updated UserService to utilize these identifiers.
16
+ - Improved localization files to include new keys for error messages related to token absence.
17
+
18
+ This update improves the application's configuration management and localization, enhancing developer experience and user feedback.
19
+
3
20
  ## 0.4.2
4
21
 
5
22
  ### Patch Changes
@@ -1,32 +1,58 @@
1
- # Logs
2
- logs
3
- *.log
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ node_modules
5
+ /.pnp
6
+ .pnp.js
7
+
8
+ # testing
9
+ /coverage
10
+
11
+ # next.js
12
+ /.next/
13
+ /out/
14
+
15
+ # production
16
+ /build
17
+
18
+ # misc
19
+ .DS_Store
20
+ *.pem
21
+
22
+ # debug
4
23
  npm-debug.log*
5
24
  yarn-debug.log*
6
25
  yarn-error.log*
7
- pnpm-debug.log*
8
- lerna-debug.log*
26
+ .pnpm-debug.log*
27
+
28
+ # local env files
29
+ .env*.*
30
+ !.env.template
31
+
32
+ # vercel
33
+ .vercel
9
34
 
10
- node_modules
11
- dist
12
- dist-ssr
13
- *.local
14
35
  # typescript
15
36
  *.tsbuildinfo
37
+ next-env.d.ts
16
38
 
17
- # Editor directories and files
18
- .vscode/*
19
- !.vscode/extensions.json
20
- .idea
21
- .DS_Store
22
- *.suo
23
- *.ntvs*
24
- *.njsproj
25
- *.sln
26
- *.sw?
39
+ .husky
40
+ !packages/create-app/configs/_common/.husky
41
+ public/robots.txt
42
+ public/sitemap*.xml
43
+ dist
44
+ .eslintcache
45
+ .npmrc
46
+ .secrets
47
+
48
+ # local output dir
49
+ *.output/
27
50
 
28
- # lock
51
+ # lock file
52
+ package-lock.json
29
53
  yarn.lock
30
- pnpm-lock.yaml
31
- pnpm-lock.yml
32
- package-lock.json
54
+
55
+ rollup.config-*.*js
56
+
57
+ .nx/cache
58
+ .nx/workspace-data
package/dist/index.js CHANGED
@@ -2378,7 +2378,7 @@ var Generator = class {
2378
2378
 
2379
2379
  // package.json
2380
2380
  var package_default = {
2381
- version: "0.4.2",
2381
+ version: "0.4.3",
2382
2382
  description: "Create a new app with a single command"};
2383
2383
  function programArgs() {
2384
2384
  const program = new Command();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qlover/create-app",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Create a new app with a single command",
5
5
  "private": false,
6
6
  "type": "module",
@@ -15,7 +15,7 @@ VITE_SERVER_PORT=3200
15
15
  # ===== app config
16
16
  VITE_USER_TOKEN_STORAGE_KEY=fe_user_token
17
17
  VITE_OPEN_AI_MODELS='["gpt-4o-mini","gpt-3.5-turbo","gpt-3.5-turbo-2","gpt-4","gpt-4-32k"]'
18
- VITE_OPEN_AI_BASE_URL=https://api.openai.com/v1
18
+ VITE_OPEN_AI_BASE_URL=
19
19
  VITE_OPEN_AI_TOKEN=sk-proj-1234567890
20
20
  VITE_OPEN_AI_TOKEN_PREFIX=Bearer
21
21
  VITE_OPEN_AI_REQUIRE_TOKEN=true
@@ -72,6 +72,25 @@ pnpm test
72
72
  - 支持服务自动注册和依赖管理
73
73
  - 提供完整的类型推导
74
74
 
75
+ ### env 配置注入
76
+
77
+ [vite 环境变量和模式](https://cn.vite.dev/guide/env-and-mode#env-variables-and-modes)
78
+
79
+ `vite dev` 默认 NODE_ENV 表示为 development, 他会加载可能的 `.env[mode]` 文件, 比如 .env.local -> .env
80
+
81
+ `vite build`默认 NODE_ENV 表示为 production, 他会加载可能的 `.env[mode]` 文件, 比如 .env.production -> .env
82
+
83
+ Nodejs NODE_ENV 只支持 development,production,test
84
+
85
+ 这个和 vite 中的 mode 是完全不一样的, mode 可以根据 `--mode` 指定不同模式,来加载不同的 env 配置
86
+
87
+ 比如:
88
+
89
+ ```bash
90
+ vite dev --mode staging # 加载 .env.staging
91
+ vite dev --mode local # 加载 .env.local
92
+ ```
93
+
75
94
  ### 国际化支持
76
95
 
77
96
  - 基于 i18next 的完整国际化解决方案
@@ -8,9 +8,17 @@
8
8
  "email": "john.doe@example.com",
9
9
  "picture": "https://randomuser.me/api/portraits/men/1.jpg"
10
10
  },
11
+ "GET /api/userinfo": {
12
+ "name": "John Doe",
13
+ "email": "john.doe@example.com",
14
+ "picture": "https://randomuser.me/api/portraits/men/1.jpg"
15
+ },
11
16
  "POST https://feapi.example.com/api/login": {
12
17
  "token": "asdfasdf123123asdfasdf"
13
18
  },
19
+ "POST /api/login": {
20
+ "token": "/api/login-token-adfasdfasdf"
21
+ },
14
22
  "POST https://api.openai.com/v1/chat/completions": {
15
23
  "id": "chatcmpl-1234567890",
16
24
  "object": "chat.completion",
@@ -25,3 +25,10 @@ export const GLOBAL_NO_WINDOW = 'err.global.no.window';
25
25
  * @localEn Must be used in PageProvider
26
26
  */
27
27
  export const WITHIN_PAGE_PROVIDER = 'err.within.page.provider';
28
+
29
+ /**
30
+ * @description 响应内容没有 token 值
31
+ * @localZh 响应内容没有 token 值
32
+ * @localEn Response not token value
33
+ */
34
+ export const RES_NO_TOKEN = 'response.no.token';
@@ -43,7 +43,9 @@
43
43
  "fe-release": "./bin/release.js"
44
44
  },
45
45
  "scripts": {
46
- "dev": "vite",
46
+ "dev": "vite --mode localhost",
47
+ "dev:staging": "vite --mode staging",
48
+ "dev:prod": "vite --mode production",
47
49
  "build": "vite build",
48
50
  "lint": "eslint ./src --fix",
49
51
  "prettier": "prettier --write ./src",
@@ -193,5 +193,6 @@
193
193
  "page.404.title": "404 - Page Not Found",
194
194
  "page.500.title": "500 - Server Error",
195
195
  "page.login.title": "Login",
196
- "page.register.title": "Register"
196
+ "page.register.title": "Register",
197
+ "response.no.token": "Response not token value"
197
198
  }
@@ -193,5 +193,6 @@
193
193
  "page.404.title": "404 - 页面未找到",
194
194
  "page.500.title": "500 - 服务器错误",
195
195
  "page.login.title": "登录",
196
- "page.register.title": "注册"
196
+ "page.register.title": "注册",
197
+ "response.no.token": "响应内容没有 token 值"
197
198
  }
@@ -51,7 +51,7 @@ export class AppConfig implements EnvConfigInterface {
51
51
  * Storage key for user authentication token
52
52
  * @description Injected from VITE_USER_TOKEN_STORAGE_KEY environment variable
53
53
  */
54
- readonly userTokenStorageKey = '';
54
+ readonly userTokenStorageKey = '__fe_user_token__';
55
55
 
56
56
  /**
57
57
  * Available OpenAI model configurations
@@ -10,8 +10,8 @@ import { IOCIdentifier } from '@/core/IOC';
10
10
  import { LoginInterface, RegisterFormData } from '@/base/port/LoginInterface';
11
11
  import { UserApi } from '@/base/apis/userApi/UserApi';
12
12
  import { AppError } from '@/base/cases/AppError';
13
- import { LOCAL_NO_USER_TOKEN } from '@config/Identifier/Error';
14
13
  import { StoreInterface, StoreStateInterface } from '../port/StoreInterface';
14
+ import * as errKeys from '@config/Identifier/Error';
15
15
 
16
16
  class UserServiceState implements StoreStateInterface {
17
17
  success: boolean = false;
@@ -48,8 +48,10 @@ export class UserService
48
48
  async onBefore(): Promise<void> {
49
49
  await ThreadUtil.sleep(1000);
50
50
 
51
- if (!this.userToken.getToken()) {
52
- throw new AppError(LOCAL_NO_USER_TOKEN);
51
+ const userToken = this.userToken.getToken();
52
+
53
+ if (!userToken) {
54
+ throw new AppError(errKeys.LOCAL_NO_USER_TOKEN);
53
55
  }
54
56
 
55
57
  const userInfo = await this.userApi.getUserInfo();
@@ -81,6 +83,10 @@ export class UserService
81
83
  throw response.apiCatchResult;
82
84
  }
83
85
 
86
+ if (!response.data.token) {
87
+ throw new AppError(errKeys.RES_NO_TOKEN);
88
+ }
89
+
84
90
  this.userToken.setToken(response.data.token);
85
91
 
86
92
  const userInfo = await this.userApi.getUserInfo();
@@ -2,6 +2,7 @@ import { IOC } from '@/core/IOC';
2
2
  import { UserService } from '@/base/services/UserService';
3
3
  import { Navigate, Outlet } from 'react-router-dom';
4
4
  import { useStore } from '@/uikit/hooks/useStore';
5
+ import BaseHeader from '../base/components/BaseHeader';
5
6
 
6
7
  export default function Layout() {
7
8
  const userService = IOC(UserService);
@@ -12,5 +13,12 @@ export default function Layout() {
12
13
  return <Navigate to="/" replace />;
13
14
  }
14
15
 
15
- return <Outlet />;
16
+ return (
17
+ <>
18
+ <BaseHeader />
19
+ <div className="flex-1">
20
+ <Outlet />
21
+ </div>
22
+ </>
23
+ );
16
24
  }
@@ -2,9 +2,9 @@
2
2
  --color-primary: rgba(var(--color-bg-base));
3
3
  --color-secondary: rgba(var(--color-bg-secondary));
4
4
  --color-elevated: rgba(var(--color-bg-elevated));
5
- --color-text: rgba(var(--color-text-primary));
6
- --color-text-secondary: rgba(var(--color-text-secondary));
7
- --color-text-tertiary: rgba(var(--color-text-tertiary));
5
+ --color-text: rgba(var(--text-primary));
6
+ --color-text-secondary: rgba(var(--text-secondary));
7
+ --color-text-tertiary: rgba(var(--text-tertiary));
8
8
  --color-border: rgba(var(--color-border));
9
9
  --color-brand: rgba(var(--color-brand));
10
10
  --color-brand-hover: rgba(var(--color-brand-hover));
@@ -7,9 +7,9 @@
7
7
  --color-bg-elevated: 248 250 252; /* slate-50 */
8
8
 
9
9
  /* 文字颜色 */
10
- --color-text-primary: 15 23 42; /* slate-900 */
11
- --color-text-secondary: 71 85 105; /* slate-600 */
12
- --color-text-tertiary: 100 116 139; /* slate-500 */
10
+ --text-primary: 15 23 42; /* slate-900 */
11
+ --text-secondary: 71 85 105; /* slate-600 */
12
+ --text-tertiary: 100 116 139; /* slate-500 */
13
13
 
14
14
  /* 边框颜色 */
15
15
  --color-border: 226 232 240; /* slate-200 */
@@ -7,9 +7,9 @@
7
7
  --color-bg-elevated: 51 65 85; /* slate-700 */
8
8
 
9
9
  /* 文字颜色 */
10
- --color-text-primary: 255 255 255;
11
- --color-text-secondary: 148 163 184; /* slate-400 */
12
- --color-text-tertiary: 100 116 139; /* slate-500 */
10
+ --text-primary: 255 255 255;
11
+ --text-secondary: 148 163 184; /* slate-400 */
12
+ --text-tertiary: 100 116 139; /* slate-500 */
13
13
 
14
14
  /* 边框颜色 */
15
15
  --color-border: 51 65 85; /* slate-700 */
@@ -7,9 +7,9 @@
7
7
  --color-bg-elevated: 254 205 211; /* rose-200 */
8
8
 
9
9
  /* 文字颜色 */
10
- --color-text-primary: 190 18 60; /* rose-700 */
11
- --color-text-secondary: 225 29 72; /* rose-600 */
12
- --color-text-tertiary: 244 63 94; /* rose-500 */
10
+ --text-primary: 190 18 60; /* rose-700 */
11
+ --text-secondary: 225 29 72; /* rose-600 */
12
+ --text-tertiary: 244 63 94; /* rose-500 */
13
13
 
14
14
  /* 边框颜色 */
15
15
  --color-border: 254 205 211; /* rose-200 */