@qlover/create-app 0.7.9 → 0.7.11

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 (125) hide show
  1. package/CHANGELOG.md +184 -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 +34 -0
  7. package/dist/templates/next-app/config/Identifier/common.ts +7 -0
  8. package/dist/templates/next-app/config/Identifier/index.ts +2 -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/index.ts +1 -0
  13. package/dist/templates/next-app/config/i18n/register18n.ts +44 -0
  14. package/dist/templates/next-app/eslint.config.mjs +17 -0
  15. package/dist/templates/next-app/migrations/schema/UserSchema.ts +24 -0
  16. package/dist/templates/next-app/migrations/sql/1694244000000.sql +10 -0
  17. package/dist/templates/next-app/next.config.ts +1 -0
  18. package/dist/templates/next-app/package.json +12 -2
  19. package/dist/templates/next-app/public/locales/en.json +19 -2
  20. package/dist/templates/next-app/public/locales/zh.json +19 -2
  21. package/dist/templates/next-app/src/app/[locale]/admin/layout.tsx +18 -0
  22. package/dist/templates/next-app/src/app/[locale]/admin/page.tsx +22 -0
  23. package/dist/templates/next-app/src/app/[locale]/admin/users/page.tsx +62 -0
  24. package/dist/templates/next-app/src/app/[locale]/layout.tsx +1 -1
  25. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +26 -6
  26. package/dist/templates/next-app/src/app/[locale]/login/page.tsx +7 -5
  27. package/dist/templates/next-app/src/app/[locale]/page.tsx +5 -5
  28. package/dist/templates/next-app/src/app/[locale]/register/RegisterForm.tsx +176 -0
  29. package/dist/templates/next-app/src/app/[locale]/register/page.tsx +79 -0
  30. package/dist/templates/next-app/src/app/api/admin/users/route.ts +39 -0
  31. package/dist/templates/next-app/src/app/api/user/login/route.ts +50 -0
  32. package/dist/templates/next-app/src/app/api/user/logout/route.ts +27 -0
  33. package/dist/templates/next-app/src/app/api/user/register/route.ts +50 -0
  34. package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +40 -0
  35. package/dist/templates/next-app/src/base/cases/AppConfig.ts +19 -0
  36. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +46 -0
  37. package/dist/templates/next-app/src/base/cases/PageParams.ts +1 -1
  38. package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +70 -0
  39. package/dist/templates/next-app/src/base/cases/RequestState.ts +20 -0
  40. package/dist/templates/next-app/src/base/cases/RouterService.ts +4 -0
  41. package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +67 -0
  42. package/dist/templates/next-app/src/base/cases/UserServiceApi.ts +48 -0
  43. package/dist/templates/next-app/src/base/port/AdminLayoutInterface.ts +26 -0
  44. package/dist/templates/next-app/src/base/port/AdminPageInterface.ts +87 -0
  45. package/dist/templates/next-app/src/base/port/AppApiInterface.ts +14 -0
  46. package/dist/templates/next-app/src/base/port/AppUserApiInterface.ts +15 -0
  47. package/dist/templates/next-app/src/base/port/AsyncStateInterface.ts +7 -0
  48. package/dist/templates/next-app/src/base/port/DBBridgeInterface.ts +21 -0
  49. package/dist/templates/next-app/src/base/port/DBMigrationInterface.ts +92 -0
  50. package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +3 -2
  51. package/dist/templates/next-app/src/base/port/MigrationApiInterface.ts +3 -0
  52. package/dist/templates/next-app/src/base/port/PaginationInterface.ts +6 -0
  53. package/dist/templates/next-app/src/base/port/ServerApiResponseInterface.ts +6 -0
  54. package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +3 -2
  55. package/dist/templates/next-app/src/base/services/AdminUserService.ts +45 -0
  56. package/dist/templates/next-app/src/base/services/I18nService.ts +9 -45
  57. package/dist/templates/next-app/src/base/services/UserService.ts +9 -8
  58. package/dist/templates/next-app/src/base/services/adminApi/AdminApiRequester.ts +21 -0
  59. package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +34 -0
  60. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +63 -0
  61. package/dist/templates/next-app/src/base/services/appApi/AppApiRequester.ts +56 -0
  62. package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +71 -0
  63. package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +49 -0
  64. package/dist/templates/next-app/src/base/services/migrations/MigrationsApi.ts +43 -0
  65. package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +1 -1
  66. package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +26 -12
  67. package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +5 -4
  68. package/dist/templates/next-app/src/core/bootstraps/PrintBootstrap.ts +1 -1
  69. package/dist/templates/next-app/src/core/clientIoc/ClientIOC.ts +1 -1
  70. package/dist/templates/next-app/src/core/clientIoc/ClientIOCRegister.ts +1 -1
  71. package/dist/templates/next-app/src/core/globals.ts +1 -1
  72. package/dist/templates/next-app/src/core/serverIoc/ServerIOC.ts +1 -1
  73. package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +1 -1
  74. package/dist/templates/next-app/src/server/AppErrorApi.ts +10 -0
  75. package/dist/templates/next-app/src/server/AppSuccessApi.ts +7 -0
  76. package/dist/templates/next-app/src/server/PasswordEncrypt.ts +12 -0
  77. package/dist/templates/next-app/src/server/ServerAuth.ts +60 -0
  78. package/dist/templates/next-app/src/server/SupabaseBridge.ts +159 -0
  79. package/dist/templates/next-app/src/server/UserCredentialToken.ts +49 -0
  80. package/dist/templates/next-app/src/server/port/CrentialTokenInterface.ts +5 -0
  81. package/dist/templates/next-app/src/server/port/DBTableInterface.ts +10 -0
  82. package/dist/templates/next-app/src/server/port/ServerAuthInterface.ts +11 -0
  83. package/dist/templates/next-app/src/server/port/ServerInterface.ts +22 -0
  84. package/dist/templates/next-app/src/server/port/UserRepositoryInterface.ts +15 -0
  85. package/dist/templates/next-app/src/server/port/UserServiceInterface.ts +8 -0
  86. package/dist/templates/next-app/src/server/port/ValidatorInterface.ts +23 -0
  87. package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +94 -0
  88. package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +19 -0
  89. package/dist/templates/next-app/src/server/services/ApiUserService.ts +26 -0
  90. package/dist/templates/next-app/src/server/services/UserService.ts +105 -0
  91. package/dist/templates/next-app/src/server/validators/LoginValidator.ts +79 -0
  92. package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +48 -0
  93. package/dist/templates/next-app/src/styles/css/antd-themes/{_default.css → _common/_default.css} +74 -1
  94. package/dist/templates/next-app/src/styles/css/antd-themes/{dark.css → _common/dark.css} +73 -0
  95. package/dist/templates/next-app/src/styles/css/antd-themes/_common/index.css +3 -0
  96. package/dist/templates/next-app/src/styles/css/antd-themes/{pink.css → _common/pink.css} +70 -0
  97. package/dist/templates/next-app/src/styles/css/antd-themes/index.css +4 -3
  98. package/dist/templates/next-app/src/styles/css/antd-themes/menu/_default.css +108 -0
  99. package/dist/templates/next-app/src/styles/css/antd-themes/menu/dark.css +67 -0
  100. package/dist/templates/next-app/src/styles/css/antd-themes/menu/index.css +3 -0
  101. package/dist/templates/next-app/src/styles/css/antd-themes/menu/pink.css +67 -0
  102. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/_default.css +33 -0
  103. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/dark.css +32 -0
  104. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/index.css +3 -0
  105. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/pink.css +35 -0
  106. package/dist/templates/next-app/src/styles/css/antd-themes/table/_default.css +44 -0
  107. package/dist/templates/next-app/src/styles/css/antd-themes/table/dark.css +43 -0
  108. package/dist/templates/next-app/src/styles/css/antd-themes/table/index.css +3 -0
  109. package/dist/templates/next-app/src/styles/css/antd-themes/table/pink.css +43 -0
  110. package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +106 -0
  111. package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +68 -17
  112. package/dist/templates/next-app/src/uikit/components/BaseLayout.tsx +6 -1
  113. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +9 -2
  114. package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +11 -3
  115. package/dist/templates/next-app/src/uikit/components/LanguageSwitcher.tsx +1 -1
  116. package/dist/templates/next-app/src/uikit/components/LogoutButton.tsx +21 -11
  117. package/dist/templates/next-app/src/uikit/hook/useIOC.ts +1 -1
  118. package/dist/templates/next-app/src/uikit/hook/useMountedClient.ts +7 -1
  119. package/dist/templates/next-app/tsconfig.json +3 -1
  120. package/package.json +2 -2
  121. package/dist/templates/next-app/src/base/cases/ServerAuth.ts +0 -17
  122. package/dist/templates/next-app/src/base/cases/ServerErrorHandler.ts +0 -27
  123. package/dist/templates/next-app/src/base/port/ServerAuthInterface.ts +0 -3
  124. package/dist/templates/next-app/src/base/port/ServerInterface.ts +0 -12
  125. /package/dist/templates/next-app/src/{app/[locale]/login → uikit/components}/FeatureItem.tsx +0 -0
@@ -0,0 +1,63 @@
1
+ import {
2
+ ExecutorError,
3
+ RequestError,
4
+ type ExecutorContext,
5
+ type ExecutorPlugin
6
+ } from '@qlover/fe-corekit';
7
+ import type { AppApiErrorInterface } from '@/base/port/AppApiInterface';
8
+ import type { AppApiConfig } from './AppApiRequester';
9
+
10
+ export class AppApiPlugin implements ExecutorPlugin {
11
+ readonly pluginName = 'AppApiPlugin';
12
+
13
+ isAppApiErrorInterface(value: unknown): value is AppApiErrorInterface {
14
+ return (
15
+ typeof value === 'object' &&
16
+ value !== null &&
17
+ 'success' in value &&
18
+ value.success === false &&
19
+ 'id' in value &&
20
+ typeof value.id === 'string'
21
+ );
22
+ }
23
+
24
+ onSuccess(context: ExecutorContext<unknown>): void | Promise<void> {
25
+ const response = context.returnValue;
26
+
27
+ if (this.isAppApiErrorInterface(response)) {
28
+ throw new Error(response.message || response.id);
29
+ }
30
+ }
31
+
32
+ async onError(
33
+ context: ExecutorContext<AppApiConfig>
34
+ ): Promise<ExecutorError | void> {
35
+ const { error, parameters } = context;
36
+
37
+ if (error instanceof RequestError && parameters.responseType === 'json') {
38
+ // @ts-expect-error response is not defined in Error
39
+ let response = error?.response;
40
+
41
+ if (response instanceof Response) {
42
+ // clone the response to avoid mutating the original response
43
+ response = response.clone();
44
+
45
+ const json = await this.getResponseJson(response);
46
+
47
+ if (this.isAppApiErrorInterface(json)) {
48
+ const newError = new ExecutorError(json.message || json.id);
49
+ // context.error = newError;
50
+ return newError;
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ protected async getResponseJson(response: Response): Promise<unknown> {
57
+ try {
58
+ return await response.json();
59
+ } catch {
60
+ return {};
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,56 @@
1
+ import {
2
+ FetchAbortPlugin,
3
+ RequestAdapterFetch,
4
+ RequestTransaction
5
+ } from '@qlover/fe-corekit';
6
+ import { inject, injectable } from 'inversify';
7
+ import type { RequestEncryptPluginProps } from '@/base/cases/RequestEncryptPlugin';
8
+ import type { AppApiResult } from '@/base/port/AppApiInterface';
9
+ import type {
10
+ RequestAdapterConfig,
11
+ RequestAdapterResponse,
12
+ RequestTransactionInterface
13
+ } from '@qlover/fe-corekit';
14
+
15
+ export interface AppApiConfig<Request = unknown>
16
+ extends RequestAdapterConfig<Request>,
17
+ RequestEncryptPluginProps<Request> {}
18
+
19
+ /**
20
+ * UserApiResponse
21
+ *
22
+ * @description
23
+ * UserApiResponse is the response for the UserApi.
24
+ *
25
+ * extends:
26
+ * - RequestAdapterResponse<Request, Response>
27
+ */
28
+ export type AppApiResponse<
29
+ Request = unknown,
30
+ Response = unknown
31
+ > = RequestAdapterResponse<Request, AppApiResult<Response>>;
32
+
33
+ /**
34
+ * UserApi common transaction
35
+ */
36
+ export interface AppApiTransaction<Request = unknown, Response = unknown>
37
+ extends RequestTransactionInterface<
38
+ AppApiConfig<Request>,
39
+ AppApiResponse<Request, Response>
40
+ > {
41
+ data: AppApiConfig<Request>['data'];
42
+ }
43
+
44
+ @injectable()
45
+ export class AppApiRequester extends RequestTransaction<AppApiConfig> {
46
+ constructor(
47
+ @inject(FetchAbortPlugin) protected abortPlugin: FetchAbortPlugin
48
+ ) {
49
+ super(
50
+ new RequestAdapterFetch({
51
+ baseURL: '/api',
52
+ responseType: 'json'
53
+ })
54
+ );
55
+ }
56
+ }
@@ -0,0 +1,71 @@
1
+ import { inject, injectable } from 'inversify';
2
+ import type { AppApiResult } from '@/base/port/AppApiInterface';
3
+ import type { AppUserApiInterface } from '@/base/port/AppUserApiInterface';
4
+ import { AppApiRequester } from './AppApiRequester';
5
+ import type { AppApiConfig, AppApiTransaction } from './AppApiRequester';
6
+ import type { RequestTransaction } from '@qlover/fe-corekit';
7
+
8
+ export type UserApiLoginTransaction = AppApiTransaction<
9
+ { email: string; password: string },
10
+ {
11
+ token: string;
12
+ }
13
+ >;
14
+
15
+ export type UserApiRegisterTransaction = AppApiTransaction<
16
+ {
17
+ email: string;
18
+ password: string;
19
+ },
20
+ AppApiTransaction['response']['data']
21
+ >;
22
+
23
+ /**
24
+ * UserApi
25
+ *
26
+ * @description
27
+ * UserApi is a client for the user API.
28
+ *
29
+ */
30
+ @injectable()
31
+ export class AppUserApi implements AppUserApiInterface {
32
+ constructor(
33
+ @inject(AppApiRequester)
34
+ protected client: RequestTransaction<AppApiConfig>
35
+ ) {}
36
+
37
+ async login(
38
+ params: UserApiLoginTransaction['data']
39
+ ): Promise<AppApiResult<unknown>> {
40
+ const response = await this.client.request<UserApiLoginTransaction>({
41
+ url: '/user/login',
42
+ method: 'POST',
43
+ data: params,
44
+ encryptProps: 'password'
45
+ });
46
+
47
+ return response.data;
48
+ }
49
+
50
+ async register(
51
+ params: UserApiRegisterTransaction['data']
52
+ ): Promise<AppApiResult<unknown>> {
53
+ const response = await this.client.request<UserApiRegisterTransaction>({
54
+ url: '/user/register',
55
+ method: 'POST',
56
+ data: params,
57
+ encryptProps: 'password'
58
+ });
59
+
60
+ return response.data;
61
+ }
62
+
63
+ async logout(): Promise<AppApiResult<unknown>> {
64
+ const response = await this.client.request({
65
+ url: '/user/logout',
66
+ method: 'POST'
67
+ });
68
+
69
+ return response.data as AppApiResult<unknown>;
70
+ }
71
+ }
@@ -0,0 +1,49 @@
1
+ import { RequestCommonPlugin } from '@qlover/corekit-bridge';
2
+ import { FetchURLPlugin } from '@qlover/fe-corekit';
3
+ import { DialogErrorPlugin } from '@/base/cases/DialogErrorPlugin';
4
+ import { RequestEncryptPlugin } from '@/base/cases/RequestEncryptPlugin';
5
+ import { StringEncryptor } from '@/base/cases/StringEncryptor';
6
+ import { AppApiPlugin } from './AppApiPlugin';
7
+ import { AppApiRequester } from './AppApiRequester';
8
+ import type { AppApiConfig } from './AppApiRequester';
9
+ import type {
10
+ BootstrapContext,
11
+ BootstrapExecutorPlugin
12
+ } from '@qlover/corekit-bridge';
13
+ import type { ExecutorContext, SerializerIneterface } from '@qlover/fe-corekit';
14
+
15
+ export class AppUserApiBootstrap implements BootstrapExecutorPlugin {
16
+ readonly pluginName = 'AppUserApiBootstrap';
17
+
18
+ constructor(protected serializer: SerializerIneterface) {}
19
+
20
+ onBefore({ parameters: { ioc } }: BootstrapContext): void | Promise<void> {
21
+ const appUserApi = ioc.get<AppApiRequester>(AppApiRequester);
22
+
23
+ appUserApi.usePlugin(new FetchURLPlugin());
24
+ appUserApi.usePlugin(new RequestEncryptPlugin(ioc.get(StringEncryptor)));
25
+ appUserApi.usePlugin(
26
+ new RequestCommonPlugin({
27
+ requestDataSerializer: this.requestDataSerializer.bind(this)
28
+ })
29
+ );
30
+ appUserApi.usePlugin(new AppApiPlugin());
31
+ appUserApi.usePlugin(ioc.get(DialogErrorPlugin));
32
+ console.log('jj AppUserApiBootstrap success');
33
+ }
34
+
35
+ protected requestDataSerializer(
36
+ data: unknown,
37
+ context: ExecutorContext<AppApiConfig>
38
+ ): unknown {
39
+ if (data instanceof FormData) {
40
+ return data;
41
+ }
42
+
43
+ if (context.parameters?.responseType === 'json') {
44
+ return this.serializer.serialize(data);
45
+ }
46
+
47
+ return data;
48
+ }
49
+ }
@@ -0,0 +1,43 @@
1
+ import { RequestCommonPlugin } from '@qlover/corekit-bridge';
2
+ import {
3
+ FetchAbortPlugin,
4
+ RequestTransaction,
5
+ RequestAdapterFetch,
6
+ FetchURLPlugin
7
+ } from '@qlover/fe-corekit';
8
+ import { inject, injectable } from 'inversify';
9
+ import type { MigrationApiInterface } from '@/base/port/MigrationApiInterface';
10
+ import type { RequestAdapterConfig } from '@qlover/fe-corekit';
11
+
12
+ /**
13
+ * UserApi
14
+ *
15
+ * @description
16
+ * UserApi is a client for the user API.
17
+ *
18
+ */
19
+ @injectable()
20
+ export class MigrationsApi
21
+ extends RequestTransaction<RequestAdapterConfig>
22
+ implements MigrationApiInterface
23
+ {
24
+ constructor(
25
+ @inject(FetchAbortPlugin) protected abortPlugin: FetchAbortPlugin
26
+ ) {
27
+ super(
28
+ new RequestAdapterFetch({
29
+ baseURL: '/api/admin/migrations',
30
+ responseType: 'json'
31
+ })
32
+ );
33
+
34
+ this.usePlugin(new FetchURLPlugin()).usePlugin(new RequestCommonPlugin());
35
+ }
36
+
37
+ async init(): Promise<unknown> {
38
+ return this.request({
39
+ url: '/init',
40
+ method: 'POST'
41
+ });
42
+ }
43
+ }
@@ -1,9 +1,9 @@
1
1
  import { Bootstrap } from '@qlover/corekit-bridge';
2
2
  import { isObject } from 'lodash';
3
3
  import { browserGlobalsName } from '@config/common';
4
+ import type { IOCIdentifierMap } from '@config/IOCIdentifier';
4
5
  import { BootstrapsRegistry } from './BootstrapsRegistry';
5
6
  import * as globals from '../globals';
6
- import type { IOCIdentifierMap } from '@config/IOCIdentifier';
7
7
  import type {
8
8
  IOCContainerInterface,
9
9
  IOCFunctionInterface
@@ -1,23 +1,23 @@
1
1
  import {
2
+ type ServiceIdentifier,
2
3
  type BootstrapContextValue,
3
4
  type BootstrapExecutorPlugin,
4
5
  type IOCContainerInterface,
5
6
  type IOCFunctionInterface,
6
7
  type LoggerInterface
7
8
  } from '@qlover/corekit-bridge';
8
- import { AsyncExecutor, type ExecutorPlugin } from '@qlover/fe-corekit';
9
+ import {
10
+ AsyncExecutor,
11
+ type ExecutorError,
12
+ type PromiseTask,
13
+ type ExecutorPlugin
14
+ } from '@qlover/fe-corekit';
15
+ import type { ServerInterface } from '@/server/port/ServerInterface';
9
16
  import { I, type IOCIdentifierMapServer } from '@config/IOCIdentifier';
10
- import type { ServerInterface } from '@/base/port/ServerInterface';
11
17
  import { ServerIOC } from '../serverIoc/ServerIOC';
12
18
 
13
- export interface BootstrapServerResult {
14
- locale: string;
15
- messages: Record<string, string>;
16
- }
17
-
18
19
  export interface BootstrapServerContextValue extends BootstrapContextValue {
19
- locale: string;
20
- messages: Record<string, string>;
20
+ IOC: IOCFunctionInterface<IOCIdentifierMapServer, IOCContainerInterface>;
21
21
  }
22
22
 
23
23
  export class BootstrapServer implements ServerInterface {
@@ -43,11 +43,12 @@ export class BootstrapServer implements ServerInterface {
43
43
  getIOC<T extends keyof IOCIdentifierMapServer>(
44
44
  identifier: T
45
45
  ): IOCIdentifierMapServer[T];
46
- getIOC(
47
- identifier?: keyof IOCIdentifierMapServer
46
+ getIOC<T>(serviceIdentifier: ServiceIdentifier<T>): T;
47
+ getIOC<T extends keyof IOCIdentifierMapServer>(
48
+ identifier?: T
48
49
  ):
49
50
  | IOCFunctionInterface<IOCIdentifierMapServer, IOCContainerInterface>
50
- | IOCIdentifierMapServer[keyof IOCIdentifierMapServer] {
51
+ | IOCIdentifierMapServer[T] {
51
52
  if (identifier === undefined) {
52
53
  return this.IOC;
53
54
  }
@@ -75,4 +76,17 @@ export class BootstrapServer implements ServerInterface {
75
76
  this.executor.use(plugin as ExecutorPlugin<unknown>);
76
77
  return this;
77
78
  }
79
+
80
+ execNoError<Result>(
81
+ task?: PromiseTask<Result, BootstrapServerContextValue>
82
+ ): Promise<Result | ExecutorError> {
83
+ const context = {
84
+ logger: this.logger,
85
+ root: this.root,
86
+ ioc: this.IOC.implemention!,
87
+ IOC: this.IOC
88
+ };
89
+
90
+ return this.executor.execNoError(context, task);
91
+ }
78
92
  }
@@ -1,8 +1,9 @@
1
- import { IOCIdentifier } from '@config/IOCIdentifier';
1
+ import { AppUserApiBootstrap } from '@/base/services/appApi/AppUserApiBootstrap';
2
+ import { I, IOCIdentifier } from '@config/IOCIdentifier';
3
+ import type { IOCIdentifierMap } from '@config/IOCIdentifier';
2
4
  import { IocIdentifierTest } from './IocIdentifierTest';
3
5
  import { printBootstrap } from './PrintBootstrap';
4
6
  import type { BootstrapAppArgs } from './BootstrapClient';
5
- import type { IOCIdentifierMap } from '@config/IOCIdentifier';
6
7
  import type {
7
8
  BootstrapExecutorPlugin,
8
9
  EnvConfigInterface,
@@ -28,8 +29,8 @@ export class BootstrapsRegistry {
28
29
  i18nService.setPathname(this.args.pathname);
29
30
 
30
31
  const bootstrapList: BootstrapExecutorPlugin[] = [
31
- i18nService
32
- // new UserApiBootstarp(),
32
+ i18nService,
33
+ new AppUserApiBootstrap(IOC(I.JSONSerializer))
33
34
  // new FeApiBootstarp(),
34
35
  // AiApiBootstarp,
35
36
  // IOC(IOCIdentifier.I18nKeyErrorPlugin)
@@ -1,5 +1,5 @@
1
- import { browserGlobalsName } from '@config/common';
2
1
  import { AppConfig } from '@/base/cases/AppConfig';
2
+ import { browserGlobalsName } from '@config/common';
3
3
  import type { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
4
4
 
5
5
  export const printBootstrap: BootstrapExecutorPlugin = {
@@ -5,9 +5,9 @@ import {
5
5
  } from '@qlover/corekit-bridge';
6
6
  import { InversifyContainer } from '@/base/cases/InversifyContainer';
7
7
  import type { IOCInterface } from '@/base/port/IOCInterface';
8
+ import type { IOCIdentifierMap } from '@config/IOCIdentifier';
8
9
  import { ClientIOCRegister } from './ClientIOCRegister';
9
10
  import { appConfig } from '../globals';
10
- import type { IOCIdentifierMap } from '@config/IOCIdentifier';
11
11
 
12
12
  export class ClientIOC
13
13
  implements IOCInterface<IOCIdentifierMap, IOCContainerInterface>
@@ -1,8 +1,8 @@
1
- import { IOCIdentifier as I } from '@config/IOCIdentifier';
2
1
  import { RouterService } from '@/base/cases/RouterService';
3
2
  import type { IocRegisterOptions } from '@/base/port/IOCInterface';
4
3
  import { I18nService } from '@/base/services/I18nService';
5
4
  import { UserService } from '@/base/services/UserService';
5
+ import { IOCIdentifier as I } from '@config/IOCIdentifier';
6
6
  import { dialogHandler, logger, JSON } from '../globals';
7
7
  import type {
8
8
  IOCContainerInterface,
@@ -1,9 +1,9 @@
1
1
  // ! global variables, don't import any dependencies and don't have side effects
2
2
  import { ColorFormatter, ConsoleHandler, Logger } from '@qlover/corekit-bridge';
3
3
  import { JSONSerializer } from '@qlover/fe-corekit';
4
- import { loggerStyles } from '@config/common';
5
4
  import { AppConfig } from '@/base/cases/AppConfig';
6
5
  import { DialogHandler } from '@/base/cases/DialogHandler';
6
+ import { loggerStyles } from '@config/common';
7
7
 
8
8
  export const appConfig = new AppConfig();
9
9
 
@@ -6,8 +6,8 @@ import {
6
6
  import { AppConfig } from '@/base/cases/AppConfig';
7
7
  import { InversifyContainer } from '@/base/cases/InversifyContainer';
8
8
  import type { IOCInterface } from '@/base/port/IOCInterface';
9
- import { ServerIOCRegister } from './ServerIOCRegister';
10
9
  import type { IOCIdentifierMapServer } from '@config/IOCIdentifier';
10
+ import { ServerIOCRegister } from './ServerIOCRegister';
11
11
 
12
12
  export class ServerIOC
13
13
  implements IOCInterface<IOCIdentifierMapServer, IOCContainerInterface>
@@ -6,8 +6,8 @@ import {
6
6
  type IOCManagerInterface,
7
7
  type IOCRegisterInterface
8
8
  } from '@qlover/corekit-bridge';
9
- import { IOCIdentifier as I } from '@config/IOCIdentifier';
10
9
  import type { IocRegisterOptions } from '@/base/port/IOCInterface';
10
+ import { IOCIdentifier as I } from '@config/IOCIdentifier';
11
11
 
12
12
  export class ServerIOCRegister
13
13
  implements IOCRegisterInterface<IOCContainerInterface, IocRegisterOptions>
@@ -0,0 +1,10 @@
1
+ import type { AppApiErrorInterface } from '@/base/port/AppApiInterface';
2
+
3
+ export class AppErrorApi implements AppApiErrorInterface {
4
+ readonly success = false;
5
+
6
+ constructor(
7
+ public readonly id: string,
8
+ public readonly message?: string
9
+ ) {}
10
+ }
@@ -0,0 +1,7 @@
1
+ import type { AppApiSuccessInterface } from '@/base/port/AppApiInterface';
2
+
3
+ export class AppSuccessApi<T = unknown> implements AppApiSuccessInterface<T> {
4
+ readonly success = true;
5
+
6
+ constructor(public readonly data?: T) {}
7
+ }
@@ -0,0 +1,12 @@
1
+ import crypto from 'crypto';
2
+ import type { Encryptor } from '@qlover/fe-corekit';
3
+
4
+ export class PasswordEncrypt implements Encryptor<string, string> {
5
+ encrypt(password: string): string {
6
+ return crypto.createHash('md5').update(password).digest('hex');
7
+ }
8
+
9
+ decrypt(): string {
10
+ throw new Error('Md5Encrypt is not decryptable');
11
+ }
12
+ }
@@ -0,0 +1,60 @@
1
+ import { ExecutorError } from '@qlover/fe-corekit';
2
+ import { inject, injectable } from 'inversify';
3
+ import { cookies } from 'next/headers';
4
+ import type { AppConfig } from '@/base/cases/AppConfig';
5
+ import { API_NOT_AUTHORIZED } from '@config/Identifier';
6
+ import { I } from '@config/IOCIdentifier';
7
+ import { UserCredentialToken } from './UserCredentialToken';
8
+ import type { ServerAuthInterface } from './port/ServerAuthInterface';
9
+
10
+ @injectable()
11
+ export class ServerAuth implements ServerAuthInterface {
12
+ protected userTokenKey: string;
13
+ constructor(
14
+ @inject(I.AppConfig) protected server: AppConfig,
15
+ @inject(UserCredentialToken)
16
+ protected userCredentialToken: UserCredentialToken
17
+ ) {
18
+ this.userTokenKey = server.userTokenKey;
19
+ }
20
+
21
+ async setAuth(credential_token: string): Promise<void> {
22
+ const cookieStore = await cookies();
23
+
24
+ cookieStore.set(this.userTokenKey, credential_token);
25
+ }
26
+
27
+ async hasAuth(): Promise<boolean> {
28
+ const token = await this.getAuth();
29
+
30
+ if (!token) {
31
+ return false;
32
+ }
33
+
34
+ try {
35
+ const user = await this.userCredentialToken.parseToken(token);
36
+
37
+ return !!user;
38
+ } catch {
39
+ return false;
40
+ }
41
+ }
42
+
43
+ async getAuth(): Promise<string> {
44
+ const cookieStore = await cookies();
45
+ return cookieStore.get(this.userTokenKey)?.value || '';
46
+ }
47
+
48
+ async clear(): Promise<void> {
49
+ const cookieStore = await cookies();
50
+ cookieStore.delete(this.userTokenKey);
51
+ }
52
+
53
+ async throwIfNotAuth(): Promise<void> {
54
+ const hasAuth = await this.hasAuth();
55
+
56
+ if (!hasAuth) {
57
+ throw new ExecutorError(API_NOT_AUTHORIZED, 'Not authorized');
58
+ }
59
+ }
60
+ }