@qlover/create-app 0.7.8 → 0.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/CHANGELOG.md +140 -0
  2. package/dist/index.cjs +3 -3
  3. package/dist/index.js +3 -3
  4. package/dist/templates/next-app/.env.template +8 -4
  5. package/dist/templates/next-app/config/IOCIdentifier.ts +4 -1
  6. package/dist/templates/next-app/config/Identifier/api.ts +20 -0
  7. package/dist/templates/next-app/config/Identifier/index.ts +2 -0
  8. package/dist/templates/next-app/config/Identifier/page.home.ts +7 -0
  9. package/dist/templates/next-app/config/Identifier/page.login.ts +2 -2
  10. package/dist/templates/next-app/config/Identifier/page.register.ts +43 -22
  11. package/dist/templates/next-app/config/Identifier/validator.ts +34 -0
  12. package/dist/templates/next-app/config/i18n/HomeI18n .ts +22 -0
  13. package/dist/templates/next-app/config/i18n/index.ts +1 -0
  14. package/dist/templates/next-app/config/i18n/register18n.ts +44 -0
  15. package/dist/templates/next-app/config/theme.ts +1 -0
  16. package/dist/templates/next-app/migrations/schema/UserSchema.ts +13 -0
  17. package/dist/templates/next-app/migrations/sql/1694244000000.sql +10 -0
  18. package/dist/templates/next-app/package.json +15 -6
  19. package/dist/templates/next-app/public/locales/en.json +17 -2
  20. package/dist/templates/next-app/public/locales/zh.json +17 -2
  21. package/dist/templates/next-app/src/app/[locale]/admin/layout.tsx +21 -0
  22. package/dist/templates/next-app/src/app/[locale]/admin/page.tsx +10 -0
  23. package/dist/templates/next-app/src/app/[locale]/layout.tsx +1 -7
  24. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +28 -16
  25. package/dist/templates/next-app/src/app/[locale]/login/page.tsx +10 -17
  26. package/dist/templates/next-app/src/app/[locale]/page.tsx +94 -102
  27. package/dist/templates/next-app/src/app/[locale]/register/RegisterForm.tsx +176 -0
  28. package/dist/templates/next-app/src/app/[locale]/register/page.tsx +79 -0
  29. package/dist/templates/next-app/src/app/api/user/login/route.ts +50 -0
  30. package/dist/templates/next-app/src/app/api/user/logout/route.ts +27 -0
  31. package/dist/templates/next-app/src/app/api/user/register/route.ts +50 -0
  32. package/dist/templates/next-app/src/base/cases/AppConfig.ts +19 -0
  33. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +35 -0
  34. package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +70 -0
  35. package/dist/templates/next-app/src/base/cases/RouterService.ts +4 -0
  36. package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +67 -0
  37. package/dist/templates/next-app/src/base/cases/UserServiceApi.ts +48 -0
  38. package/dist/templates/next-app/src/base/port/AppApiInterface.ts +14 -0
  39. package/dist/templates/next-app/src/base/port/AppUserApiInterface.ts +15 -0
  40. package/dist/templates/next-app/src/base/port/DBBridgeInterface.ts +18 -0
  41. package/dist/templates/next-app/src/base/port/DBMigrationInterface.ts +92 -0
  42. package/dist/templates/next-app/src/base/port/DBTableInterface.ts +3 -0
  43. package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +3 -2
  44. package/dist/templates/next-app/src/base/port/MigrationApiInterface.ts +3 -0
  45. package/dist/templates/next-app/src/base/port/ServerApiResponseInterface.ts +6 -0
  46. package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +3 -2
  47. package/dist/templates/next-app/src/base/services/I18nService.ts +9 -45
  48. package/dist/templates/next-app/src/base/services/UserService.ts +9 -8
  49. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +63 -0
  50. package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +72 -0
  51. package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +48 -0
  52. package/dist/templates/next-app/src/base/services/appApi/AppUserType.ts +51 -0
  53. package/dist/templates/next-app/src/base/services/migrations/MigrationsApi.ts +43 -0
  54. package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +30 -5
  55. package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +4 -3
  56. package/dist/templates/next-app/src/server/AppErrorApi.ts +10 -0
  57. package/dist/templates/next-app/src/server/AppSuccessApi.ts +7 -0
  58. package/dist/templates/next-app/src/server/PasswordEncrypt.ts +12 -0
  59. package/dist/templates/next-app/src/server/ServerAuth.ts +50 -0
  60. package/dist/templates/next-app/src/server/SupabaseBridge.ts +124 -0
  61. package/dist/templates/next-app/src/server/UserCredentialToken.ts +49 -0
  62. package/dist/templates/next-app/src/server/port/CrentialTokenInterface.ts +5 -0
  63. package/dist/templates/next-app/src/server/port/ServerInterface.ts +22 -0
  64. package/dist/templates/next-app/src/server/port/UserAuthInterface.ts +9 -0
  65. package/dist/templates/next-app/src/server/port/UserRepositoryInterface.ts +15 -0
  66. package/dist/templates/next-app/src/server/port/UserServiceInterface.ts +8 -0
  67. package/dist/templates/next-app/src/server/port/ValidatorInterface.ts +23 -0
  68. package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +63 -0
  69. package/dist/templates/next-app/src/server/services/UserService.ts +105 -0
  70. package/dist/templates/next-app/src/server/validators/LoginValidator.ts +79 -0
  71. package/dist/templates/next-app/src/styles/css/antd-themes/_default.css +12 -0
  72. package/dist/templates/next-app/src/styles/css/antd-themes/dark.css +26 -0
  73. package/dist/templates/next-app/src/styles/css/antd-themes/pink.css +16 -0
  74. package/dist/templates/next-app/src/styles/css/page.css +4 -3
  75. package/dist/templates/next-app/src/styles/css/themes/_default.css +1 -0
  76. package/dist/templates/next-app/src/styles/css/themes/dark.css +1 -0
  77. package/dist/templates/next-app/src/styles/css/themes/pink.css +1 -0
  78. package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +6 -11
  79. package/dist/templates/next-app/src/uikit/components/BaseLayout.tsx +27 -0
  80. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +8 -1
  81. package/dist/templates/next-app/src/uikit/components/LanguageSwitcher.tsx +49 -21
  82. package/dist/templates/next-app/src/uikit/components/LogoutButton.tsx +20 -10
  83. package/dist/templates/next-app/src/uikit/components/ThemeSwitcher.tsx +92 -48
  84. package/dist/templates/next-app/tsconfig.json +3 -1
  85. package/package.json +2 -2
  86. package/dist/templates/next-app/src/base/cases/ServerAuth.ts +0 -17
  87. package/dist/templates/next-app/src/base/port/ServerAuthInterface.ts +0 -3
  88. package/dist/templates/next-app/src/base/port/ServerInterface.ts +0 -12
  89. /package/dist/templates/next-app/src/{app/[locale]/login → uikit/components}/FeatureItem.tsx +0 -0
@@ -1,73 +1,84 @@
1
1
  'use client';
2
2
 
3
3
  import {
4
- BulbOutlined,
5
- BulbFilled,
6
4
  HeartFilled,
7
- HeartOutlined,
8
- DesktopOutlined
5
+ SettingOutlined,
6
+ SunOutlined,
7
+ MoonOutlined,
8
+ SettingFilled,
9
+ SunFilled,
10
+ MoonFilled,
11
+ HeartOutlined
9
12
  } from '@ant-design/icons';
10
- import { Select } from 'antd';
13
+ import { Dropdown } from 'antd';
11
14
  import { clsx } from 'clsx';
12
15
  import { useTheme } from 'next-themes';
13
- import { themeConfig } from '@config/theme';
16
+ import { useMemo } from 'react';
17
+ import { type SupportedTheme, themeConfig } from '@config/theme';
14
18
  import { useMountedClient } from '../hook/useMountedClient';
19
+ import type { ItemType } from 'antd/es/menu/interface';
15
20
 
16
21
  const { supportedThemes } = themeConfig;
17
22
 
23
+ const defaultTheme = supportedThemes[0] || 'system';
24
+ const themesList = ['system', ...supportedThemes];
25
+
18
26
  const colorMap: Record<
19
27
  string,
20
- { i18nkey: string; colors: string[]; icons: React.ElementType[] }
28
+ {
29
+ i18nkey: string;
30
+ selectedColor: string;
31
+ normalColor: string;
32
+ Icon: React.ElementType;
33
+ SelectedIcon: React.ElementType;
34
+ TriggerIcon: React.ElementType;
35
+ }
21
36
  > = {
22
37
  system: {
23
38
  i18nkey: 'System',
24
- colors: ['text-text', 'text-text-secondary'],
25
- icons: [DesktopOutlined, DesktopOutlined]
39
+ selectedColor: 'text-text',
40
+ normalColor: 'text-text-secondary',
41
+ Icon: SettingOutlined,
42
+ SelectedIcon: SettingFilled,
43
+ TriggerIcon: SettingOutlined
26
44
  },
27
45
  light: {
28
46
  i18nkey: 'Light',
29
- colors: ['text-text', 'text-text-secondary'],
30
- icons: [BulbFilled, BulbOutlined]
47
+ selectedColor: 'text-text',
48
+ normalColor: 'text-text-secondary',
49
+ Icon: SunOutlined,
50
+ SelectedIcon: SunFilled,
51
+ TriggerIcon: SunOutlined
31
52
  },
32
53
  dark: {
33
54
  i18nkey: 'Dark',
34
- colors: ['text-[#9333ea]', 'text-[#a855f7]'],
35
- icons: [BulbFilled, BulbOutlined]
55
+ selectedColor: 'text-[#9333ea]',
56
+ normalColor: 'text-[#a855f7]',
57
+ Icon: MoonOutlined,
58
+ SelectedIcon: MoonFilled,
59
+ TriggerIcon: MoonOutlined
36
60
  },
37
61
  pink: {
38
62
  i18nkey: 'Pink',
39
- colors: ['text-[#f472b6]', 'text-[#ec4899]'],
40
- icons: [HeartFilled, HeartOutlined]
63
+ selectedColor: 'text-[#f472b6]',
64
+ normalColor: 'text-[#ec4899]',
65
+ Icon: HeartOutlined,
66
+ SelectedIcon: HeartFilled,
67
+ TriggerIcon: HeartOutlined
41
68
  }
42
69
  };
43
70
 
44
71
  export function ThemeSwitcher() {
45
- const { theme, resolvedTheme, setTheme } = useTheme();
72
+ const { theme: currentTheme, resolvedTheme, setTheme } = useTheme();
46
73
  const mounted = useMountedClient();
47
74
 
48
- // 如果组件未挂载,返回空的 Select 以避免闪烁
49
- if (!mounted) {
50
- return (
51
- <Select
52
- data-testid="ThemeSwitcher"
53
- loading
54
- value="system"
55
- options={[]}
56
- style={{ width: 120 }}
57
- className="min-w-40 max-w-full"
58
- disabled
59
- />
60
- );
61
- }
62
-
63
- const themeOptions = ['system', ...supportedThemes!].map((themeName) => {
64
- const { i18nkey, colors, icons } = colorMap[themeName] || colorMap.light;
65
- const [currentColor, normalColor] = colors;
66
- const [CurrentIcon, NormalIcon] = icons;
75
+ const themeOptions = themesList.map((themeName) => {
76
+ const { i18nkey, selectedColor, normalColor, Icon, SelectedIcon } =
77
+ colorMap[themeName] || colorMap.light;
67
78
 
68
79
  const isCurrentTheme =
69
- theme === themeName ||
70
- (themeName === resolvedTheme && theme === 'system');
80
+ currentTheme === themeName ||
81
+ (themeName === resolvedTheme && currentTheme === 'system');
71
82
 
72
83
  return {
73
84
  key: themeName,
@@ -76,24 +87,57 @@ export function ThemeSwitcher() {
76
87
  <div
77
88
  className={clsx(
78
89
  'flex items-center gap-2',
79
- isCurrentTheme ? currentColor : normalColor
90
+ isCurrentTheme ? selectedColor : normalColor
80
91
  )}
81
92
  >
82
- {isCurrentTheme ? <CurrentIcon /> : <NormalIcon />}
93
+ {isCurrentTheme ? <SelectedIcon /> : <Icon />}
83
94
  <span>{i18nkey}</span>
84
95
  </div>
85
96
  )
86
- };
97
+ } as ItemType;
87
98
  });
88
99
 
100
+ const nextTheme = useMemo(() => {
101
+ if (!currentTheme) {
102
+ return defaultTheme;
103
+ }
104
+ const targetIndex =
105
+ supportedThemes.indexOf(currentTheme as SupportedTheme) + 1;
106
+ return supportedThemes[targetIndex % supportedThemes.length];
107
+ }, [currentTheme]);
108
+
109
+ const TriggerIcon = colorMap[currentTheme || defaultTheme].TriggerIcon;
110
+
111
+ if (!mounted) {
112
+ return (
113
+ <span
114
+ data-testid="ThemeSwitcher"
115
+ className="text-text hover:text-text-hover cursor-pointer text-lg transition-colors"
116
+ >
117
+ <SettingOutlined />
118
+ </span>
119
+ );
120
+ }
121
+
89
122
  return (
90
- <Select
91
- data-testid="ThemeSwitcher"
92
- value={theme}
93
- onChange={setTheme}
94
- options={themeOptions}
95
- style={{ width: 120 }}
96
- className="min-w-40 max-w-full"
97
- />
123
+ <Dropdown
124
+ data-testid="ThemeSwitcherDropdown"
125
+ trigger={['hover']}
126
+ menu={{
127
+ items: themeOptions,
128
+ selectedKeys: [currentTheme!],
129
+ onClick: ({ key }) => {
130
+ setTheme(key);
131
+ }
132
+ }}
133
+ >
134
+ <span
135
+ data-testid="ThemeSwitcher"
136
+ className="text-text hover:text-text-hover cursor-pointer text-lg transition-colors"
137
+ onClick={() => setTheme(nextTheme)}
138
+ >
139
+ <TriggerIcon />
140
+ </span>
141
+ </Dropdown>
98
142
  );
99
143
  }
@@ -22,13 +22,15 @@
22
22
  ],
23
23
  "paths": {
24
24
  "@/*": ["./src/*"],
25
- "@config/*": ["./config/*"]
25
+ "@config/*": ["./config/*"],
26
+ "@migrations/*": ["./migrations/*"]
26
27
  }
27
28
  },
28
29
  "include": [
29
30
  "next-env.d.ts",
30
31
  "src/**/*.ts",
31
32
  "src/**/*.tsx",
33
+ "migrations/**/*.ts",
32
34
  ".next/types/**/*.ts",
33
35
  "config/**/*.ts"
34
36
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qlover/create-app",
3
- "version": "0.7.8",
3
+ "version": "0.7.10",
4
4
  "description": "Create a new app with a single command",
5
5
  "private": false,
6
6
  "type": "module",
@@ -38,7 +38,7 @@
38
38
  "dependencies": {
39
39
  "commander": "^13.1.0",
40
40
  "inquirer": "^12.3.2",
41
- "@qlover/scripts-context": "1.1.3"
41
+ "@qlover/scripts-context": "1.1.4"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsup",
@@ -1,17 +0,0 @@
1
- import { cookies } from 'next/headers';
2
- import { I } from '@config/IOCIdentifier';
3
- import type { ServerAuthInterface } from '../port/ServerAuthInterface';
4
- import type { ServerInterface } from '../port/ServerInterface';
5
-
6
- export class ServerAuth implements ServerAuthInterface {
7
- constructor(protected server: ServerInterface) {}
8
-
9
- async hasAuth(): Promise<boolean> {
10
- const cookieStore = await cookies();
11
- const appConfig = this.server.getIOC(I.AppConfig);
12
-
13
- const token = cookieStore.get(appConfig.userTokenKey);
14
-
15
- return !!token;
16
- }
17
- }
@@ -1,3 +0,0 @@
1
- export interface ServerAuthInterface {
2
- hasAuth(): Promise<boolean>;
3
- }
@@ -1,12 +0,0 @@
1
- import {
2
- type IOCContainerInterface,
3
- type IOCFunctionInterface
4
- } from '@qlover/corekit-bridge';
5
- import { type IOCIdentifierMapServer } from '@config/IOCIdentifier';
6
-
7
- export interface ServerInterface {
8
- getIOC(): IOCFunctionInterface<IOCIdentifierMapServer, IOCContainerInterface>;
9
- getIOC<T extends keyof IOCIdentifierMapServer>(
10
- identifier: T
11
- ): IOCIdentifierMapServer[T];
12
- }