@qlover/create-app 0.7.6 → 0.7.8

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 (104) hide show
  1. package/CHANGELOG.md +328 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/templates/next-app/.env.template +22 -0
  5. package/dist/templates/next-app/.prettierignore +58 -0
  6. package/dist/templates/next-app/README.md +36 -0
  7. package/dist/templates/next-app/build/generateLocales.ts +25 -0
  8. package/dist/templates/next-app/config/IOCIdentifier.ts +58 -0
  9. package/dist/templates/next-app/config/Identifier/common.error.ts +41 -0
  10. package/dist/templates/next-app/config/Identifier/common.ts +62 -0
  11. package/dist/templates/next-app/config/Identifier/index.ts +10 -0
  12. package/dist/templates/next-app/config/Identifier/page.about.ts +181 -0
  13. package/dist/templates/next-app/config/Identifier/page.executor.ts +272 -0
  14. package/dist/templates/next-app/config/Identifier/page.home.ts +63 -0
  15. package/dist/templates/next-app/config/Identifier/page.identifiter.ts +39 -0
  16. package/dist/templates/next-app/config/Identifier/page.jsonStorage.ts +72 -0
  17. package/dist/templates/next-app/config/Identifier/page.login.ts +165 -0
  18. package/dist/templates/next-app/config/Identifier/page.register.ts +147 -0
  19. package/dist/templates/next-app/config/Identifier/page.request.ts +182 -0
  20. package/dist/templates/next-app/config/common.ts +34 -0
  21. package/dist/templates/next-app/config/i18n/PageI18nInterface.ts +51 -0
  22. package/dist/templates/next-app/config/i18n/i18nConfig.ts +12 -0
  23. package/dist/templates/next-app/config/i18n/index.ts +3 -0
  24. package/dist/templates/next-app/config/i18n/loginI18n.ts +42 -0
  25. package/dist/templates/next-app/config/theme.ts +23 -0
  26. package/dist/templates/next-app/docs/env.md +94 -0
  27. package/dist/templates/next-app/eslint.config.mjs +181 -0
  28. package/dist/templates/next-app/next.config.ts +21 -0
  29. package/dist/templates/next-app/package.json +58 -0
  30. package/dist/templates/next-app/postcss.config.mjs +5 -0
  31. package/dist/templates/next-app/public/file.svg +1 -0
  32. package/dist/templates/next-app/public/globe.svg +1 -0
  33. package/dist/templates/next-app/public/locales/en.json +184 -0
  34. package/dist/templates/next-app/public/locales/zh.json +184 -0
  35. package/dist/templates/next-app/public/next.svg +1 -0
  36. package/dist/templates/next-app/public/vercel.svg +1 -0
  37. package/dist/templates/next-app/public/window.svg +1 -0
  38. package/dist/templates/next-app/src/app/[locale]/favicon.ico +0 -0
  39. package/dist/templates/next-app/src/app/[locale]/layout.tsx +32 -0
  40. package/dist/templates/next-app/src/app/[locale]/login/FeatureItem.tsx +13 -0
  41. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +114 -0
  42. package/dist/templates/next-app/src/app/[locale]/login/page.tsx +86 -0
  43. package/dist/templates/next-app/src/app/[locale]/not-found.tsx +24 -0
  44. package/dist/templates/next-app/src/app/[locale]/page.tsx +119 -0
  45. package/dist/templates/next-app/src/base/cases/AppConfig.ts +15 -0
  46. package/dist/templates/next-app/src/base/cases/DialogHandler.ts +92 -0
  47. package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +33 -0
  48. package/dist/templates/next-app/src/base/cases/NavigateBridge.ts +16 -0
  49. package/dist/templates/next-app/src/base/cases/PageParams.ts +74 -0
  50. package/dist/templates/next-app/src/base/cases/RouterService.ts +35 -0
  51. package/dist/templates/next-app/src/base/cases/ServerAuth.ts +17 -0
  52. package/dist/templates/next-app/src/base/cases/ServerErrorHandler.ts +27 -0
  53. package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +25 -0
  54. package/dist/templates/next-app/src/base/port/IOCInterface.ts +24 -0
  55. package/dist/templates/next-app/src/base/port/ParamsHandlerInterface.ts +11 -0
  56. package/dist/templates/next-app/src/base/port/RouterInterface.ts +11 -0
  57. package/dist/templates/next-app/src/base/port/ServerAuthInterface.ts +3 -0
  58. package/dist/templates/next-app/src/base/port/ServerInterface.ts +12 -0
  59. package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +11 -0
  60. package/dist/templates/next-app/src/base/services/I18nService.ts +115 -0
  61. package/dist/templates/next-app/src/base/services/UserService.ts +23 -0
  62. package/dist/templates/next-app/src/base/types/PageProps.ts +9 -0
  63. package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +61 -0
  64. package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +78 -0
  65. package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +47 -0
  66. package/dist/templates/next-app/src/core/bootstraps/IocIdentifierTest.ts +26 -0
  67. package/dist/templates/next-app/src/core/bootstraps/PrintBootstrap.ts +18 -0
  68. package/dist/templates/next-app/src/core/clientIoc/ClientIOC.ts +37 -0
  69. package/dist/templates/next-app/src/core/clientIoc/ClientIOCRegister.ts +97 -0
  70. package/dist/templates/next-app/src/core/globals.ts +24 -0
  71. package/dist/templates/next-app/src/core/serverIoc/ServerIOC.ts +52 -0
  72. package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +63 -0
  73. package/dist/templates/next-app/src/i18n/request.ts +21 -0
  74. package/dist/templates/next-app/src/i18n/routing.ts +30 -0
  75. package/dist/templates/next-app/src/middleware.ts +25 -0
  76. package/dist/templates/next-app/src/styles/css/antd-themes/_default.css +239 -0
  77. package/dist/templates/next-app/src/styles/css/antd-themes/dark.css +178 -0
  78. package/dist/templates/next-app/src/styles/css/antd-themes/index.css +3 -0
  79. package/dist/templates/next-app/src/styles/css/antd-themes/no-context.css +34 -0
  80. package/dist/templates/next-app/src/styles/css/antd-themes/pink.css +204 -0
  81. package/dist/templates/next-app/src/styles/css/index.css +6 -0
  82. package/dist/templates/next-app/src/styles/css/page.css +19 -0
  83. package/dist/templates/next-app/src/styles/css/tailwind.css +5 -0
  84. package/dist/templates/next-app/src/styles/css/themes/_default.css +29 -0
  85. package/dist/templates/next-app/src/styles/css/themes/dark.css +29 -0
  86. package/dist/templates/next-app/src/styles/css/themes/index.css +3 -0
  87. package/dist/templates/next-app/src/styles/css/themes/pink.css +29 -0
  88. package/dist/templates/next-app/src/styles/css/zIndex.css +9 -0
  89. package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +47 -0
  90. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +37 -0
  91. package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +50 -0
  92. package/dist/templates/next-app/src/uikit/components/LanguageSwitcher.tsx +52 -0
  93. package/dist/templates/next-app/src/uikit/components/LocaleLink.tsx +51 -0
  94. package/dist/templates/next-app/src/uikit/components/LogoutButton.tsx +34 -0
  95. package/dist/templates/next-app/src/uikit/components/NextIntlProvider.tsx +21 -0
  96. package/dist/templates/next-app/src/uikit/components/ThemeSwitcher.tsx +99 -0
  97. package/dist/templates/next-app/src/uikit/context/IOCContext.ts +13 -0
  98. package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +28 -0
  99. package/dist/templates/next-app/src/uikit/hook/useIOC.ts +37 -0
  100. package/dist/templates/next-app/src/uikit/hook/useMountedClient.ts +11 -0
  101. package/dist/templates/next-app/src/uikit/hook/useStore.ts +15 -0
  102. package/dist/templates/next-app/tailwind.config.ts +8 -0
  103. package/dist/templates/next-app/tsconfig.json +36 -0
  104. package/package.json +1 -1
@@ -0,0 +1,78 @@
1
+ import {
2
+ type BootstrapContextValue,
3
+ type BootstrapExecutorPlugin,
4
+ type IOCContainerInterface,
5
+ type IOCFunctionInterface,
6
+ type LoggerInterface
7
+ } from '@qlover/corekit-bridge';
8
+ import { AsyncExecutor, type ExecutorPlugin } from '@qlover/fe-corekit';
9
+ import { I, type IOCIdentifierMapServer } from '@config/IOCIdentifier';
10
+ import type { ServerInterface } from '@/base/port/ServerInterface';
11
+ import { ServerIOC } from '../serverIoc/ServerIOC';
12
+
13
+ export interface BootstrapServerResult {
14
+ locale: string;
15
+ messages: Record<string, string>;
16
+ }
17
+
18
+ export interface BootstrapServerContextValue extends BootstrapContextValue {
19
+ locale: string;
20
+ messages: Record<string, string>;
21
+ }
22
+
23
+ export class BootstrapServer implements ServerInterface {
24
+ protected executor: AsyncExecutor;
25
+ protected root: Record<string, unknown> = {};
26
+ protected IOC: IOCFunctionInterface<
27
+ IOCIdentifierMapServer,
28
+ IOCContainerInterface
29
+ >;
30
+ readonly logger: LoggerInterface;
31
+
32
+ constructor() {
33
+ const serverIOC = ServerIOC.create();
34
+ const ioc = serverIOC.create();
35
+ const logger = ioc(I.Logger);
36
+
37
+ this.executor = new AsyncExecutor();
38
+ this.IOC = ioc;
39
+ this.logger = logger;
40
+ }
41
+
42
+ getIOC(): IOCFunctionInterface<IOCIdentifierMapServer, IOCContainerInterface>;
43
+ getIOC<T extends keyof IOCIdentifierMapServer>(
44
+ identifier: T
45
+ ): IOCIdentifierMapServer[T];
46
+ getIOC(
47
+ identifier?: keyof IOCIdentifierMapServer
48
+ ):
49
+ | IOCFunctionInterface<IOCIdentifierMapServer, IOCContainerInterface>
50
+ | IOCIdentifierMapServer[keyof IOCIdentifierMapServer] {
51
+ if (identifier === undefined) {
52
+ return this.IOC;
53
+ }
54
+ return this.IOC(identifier);
55
+ }
56
+
57
+ /**
58
+ * @override
59
+ */
60
+ use(
61
+ plugin:
62
+ | BootstrapExecutorPlugin
63
+ | BootstrapExecutorPlugin[]
64
+ | ((
65
+ ioc: IOCFunctionInterface<
66
+ IOCIdentifierMapServer,
67
+ IOCContainerInterface
68
+ >
69
+ ) => BootstrapExecutorPlugin)
70
+ ): this {
71
+ if (typeof plugin === 'function') {
72
+ plugin = plugin(this.IOC);
73
+ }
74
+
75
+ this.executor.use(plugin as ExecutorPlugin<unknown>);
76
+ return this;
77
+ }
78
+ }
@@ -0,0 +1,47 @@
1
+ import { IOCIdentifier } from '@config/IOCIdentifier';
2
+ import { IocIdentifierTest } from './IocIdentifierTest';
3
+ import { printBootstrap } from './PrintBootstrap';
4
+ import type { BootstrapAppArgs } from './BootstrapClient';
5
+ import type { IOCIdentifierMap } from '@config/IOCIdentifier';
6
+ import type {
7
+ BootstrapExecutorPlugin,
8
+ EnvConfigInterface,
9
+ IOCContainerInterface,
10
+ IOCFunctionInterface
11
+ } from '@qlover/corekit-bridge';
12
+
13
+ export class BootstrapsRegistry {
14
+ constructor(protected args: BootstrapAppArgs) {}
15
+
16
+ get IOC(): IOCFunctionInterface<IOCIdentifierMap, IOCContainerInterface> {
17
+ return this.args.IOC;
18
+ }
19
+
20
+ get appConfig(): EnvConfigInterface {
21
+ return this.IOC(IOCIdentifier.AppConfig);
22
+ }
23
+
24
+ register(): BootstrapExecutorPlugin[] {
25
+ const IOC = this.IOC;
26
+
27
+ const i18nService = IOC(IOCIdentifier.I18nServiceInterface);
28
+ i18nService.setPathname(this.args.pathname);
29
+
30
+ const bootstrapList: BootstrapExecutorPlugin[] = [
31
+ i18nService
32
+ // new UserApiBootstarp(),
33
+ // new FeApiBootstarp(),
34
+ // AiApiBootstarp,
35
+ // IOC(IOCIdentifier.I18nKeyErrorPlugin)
36
+ ];
37
+
38
+ if (!this.appConfig.isProduction) {
39
+ bootstrapList.push(printBootstrap);
40
+ }
41
+
42
+ bootstrapList.push(IocIdentifierTest);
43
+ // TODO: 需要使用到
44
+
45
+ return bootstrapList;
46
+ }
47
+ }
@@ -0,0 +1,26 @@
1
+ import { IOCIdentifier } from '@config/IOCIdentifier';
2
+ import type { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
3
+
4
+ export const IocIdentifierTest: BootstrapExecutorPlugin = {
5
+ pluginName: 'IocIdentifierTest',
6
+ onSuccess({ parameters: { logger, ioc } }) {
7
+ const errorList: string[] = [];
8
+ const keyList: string[] = Object.keys(IOCIdentifier);
9
+ keyList.forEach((key) => {
10
+ try {
11
+ const value = ioc.get(key);
12
+ if (value === undefined) {
13
+ errorList.push(key);
14
+ }
15
+ } catch {
16
+ errorList.push(key);
17
+ }
18
+ });
19
+
20
+ if (errorList.length > 0) {
21
+ logger.warn(`IOC ${errorList.join(', ')} is not found`);
22
+ } else {
23
+ logger.info(`IOC all identifiers are found ${keyList.length}`);
24
+ }
25
+ }
26
+ };
@@ -0,0 +1,18 @@
1
+ import { browserGlobalsName } from '@config/common';
2
+ import { AppConfig } from '@/base/cases/AppConfig';
3
+ import type { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
4
+
5
+ export const printBootstrap: BootstrapExecutorPlugin = {
6
+ pluginName: 'PrintBootstrap',
7
+ onSuccess({ parameters: { logger, ioc } }) {
8
+ const appConfig = ioc.get<AppConfig>(AppConfig);
9
+ logger.info(
10
+ 'bootstrap in(' +
11
+ appConfig.env +
12
+ ')success!\n\n' +
13
+ `You can use \`%cwindow.${browserGlobalsName}%c\` to access the globals`,
14
+ 'color: #0ff; font-weight: bold;',
15
+ 'all: unset;'
16
+ );
17
+ }
18
+ };
@@ -0,0 +1,37 @@
1
+ import {
2
+ createIOCFunction,
3
+ type IOCContainerInterface,
4
+ type IOCFunctionInterface
5
+ } from '@qlover/corekit-bridge';
6
+ import { InversifyContainer } from '@/base/cases/InversifyContainer';
7
+ import type { IOCInterface } from '@/base/port/IOCInterface';
8
+ import { ClientIOCRegister } from './ClientIOCRegister';
9
+ import { appConfig } from '../globals';
10
+ import type { IOCIdentifierMap } from '@config/IOCIdentifier';
11
+
12
+ export class ClientIOC
13
+ implements IOCInterface<IOCIdentifierMap, IOCContainerInterface>
14
+ {
15
+ protected ioc: IOCFunctionInterface<
16
+ IOCIdentifierMap,
17
+ IOCContainerInterface
18
+ > | null = null;
19
+
20
+ create(): IOCFunctionInterface<IOCIdentifierMap, IOCContainerInterface> {
21
+ if (this.ioc) {
22
+ return this.ioc;
23
+ }
24
+
25
+ this.ioc = createIOCFunction<IOCIdentifierMap>(new InversifyContainer());
26
+
27
+ const register = new ClientIOCRegister({
28
+ appConfig: appConfig
29
+ });
30
+
31
+ register.register(this.ioc.implemention!, this.ioc);
32
+
33
+ return this.ioc;
34
+ }
35
+ }
36
+
37
+ export const clientIOC = new ClientIOC();
@@ -0,0 +1,97 @@
1
+ import { IOCIdentifier as I } from '@config/IOCIdentifier';
2
+ import { RouterService } from '@/base/cases/RouterService';
3
+ import type { IocRegisterOptions } from '@/base/port/IOCInterface';
4
+ import { I18nService } from '@/base/services/I18nService';
5
+ import { UserService } from '@/base/services/UserService';
6
+ import { dialogHandler, logger, JSON } from '../globals';
7
+ import type {
8
+ IOCContainerInterface,
9
+ IOCManagerInterface,
10
+ IOCRegisterInterface
11
+ } from '@qlover/corekit-bridge';
12
+
13
+ export class ClientIOCRegister
14
+ implements IOCRegisterInterface<IOCContainerInterface, IocRegisterOptions>
15
+ {
16
+ constructor(protected options: IocRegisterOptions) {}
17
+
18
+ /**
19
+ * Register globals
20
+ *
21
+ * 一般用于注册全局
22
+ *
23
+ * @param ioc - IOC container
24
+ */
25
+ protected registerGlobals(ioc: IOCContainerInterface): void {
26
+ const { appConfig } = this.options;
27
+ ioc.bind(I.JSONSerializer, JSON);
28
+ ioc.bind(I.Logger, logger);
29
+ ioc.bind(I.AppConfig, appConfig);
30
+ // ioc.bind(I.EnvConfigInterface, appConfig);
31
+ ioc.bind(I.DialogHandler, dialogHandler);
32
+ // ioc.bind(I.UIDialogInterface, dialogHandler);
33
+ // ioc.bind(I.AntdStaticApiInterface, dialogHandler);
34
+ // ioc.bind(I.LocalStorage, globals.localStorage);
35
+ // ioc.bind(I.LocalStorageEncrypt, localStorageEncrypt);
36
+ // ioc.bind(I.CookieStorage, globals.cookieStorage);
37
+ }
38
+
39
+ /**
40
+ * 一般用于注册没有其他复杂依赖的项目实现类
41
+ *
42
+ * 比如:
43
+ * - 路由服务
44
+ * - 国际化服务
45
+ * - 主题服务
46
+ *
47
+ * @param ioc
48
+ */
49
+ protected registerImplement(ioc: IOCContainerInterface): void {
50
+ ioc.bind(I.I18nServiceInterface, new I18nService());
51
+ ioc.bind(I.RouterServiceInterface, ioc.get(RouterService));
52
+ // ioc.bind(
53
+ // I.ThemeService,
54
+ // new ThemeService({
55
+ // ...themeConfig,
56
+ // storage: ioc.get<SyncStorageInterface<string, string>>(I.LocalStorage)
57
+ // })
58
+ // );
59
+ // ioc.bind(I.I18nKeyErrorPlugin, ioc.get(I18nKeyErrorPlugin));
60
+ // ioc.bind(I.ProcesserExecutorInterface, ioc.get(ProcesserExecutor));
61
+ ioc.bind(I.UserServiceInterface, ioc.get(UserService));
62
+ // ioc.bind(I.RequestCatcherInterface, ioc.get(RequestStatusCatcher));
63
+ // ioc.bind(I.ExecutorPageBridgeInterface, ioc.get(ExecutorPageBridge));
64
+ // ioc.bind(I.JSONStoragePageInterface, ioc.get(JSONStoragePageBridge));
65
+ // ioc.bind(I.RequestPageBridgeInterface, ioc.get(RequestPageBridge));
66
+ }
67
+
68
+ protected registerCommon(_ioc: IOCContainerInterface): void {
69
+ // const { appConfig } = this.options;
70
+ // const logger = ioc.get(I.Logger);
71
+ // const feApiRequestCommonPlugin = new RequestCommonPlugin({
72
+ // tokenPrefix: appConfig.openAiTokenPrefix,
73
+ // requiredToken: true,
74
+ // token: () => ioc.get(UserService).getToken()
75
+ // });
76
+ // const apiMockPlugin = new ApiMockPlugin(mockDataJson, logger);
77
+ // const apiCatchPlugin = new ApiCatchPlugin(
78
+ // logger,
79
+ // ioc.get(RequestStatusCatcher)
80
+ // );
81
+ // ioc.bind(I.FeApiCommonPlugin, feApiRequestCommonPlugin);
82
+ // ioc.bind(I.ApiMockPlugin, apiMockPlugin);
83
+ // ioc.bind(I.ApiCatchPlugin, apiCatchPlugin);
84
+ }
85
+
86
+ /**
87
+ * @override
88
+ */
89
+ register(
90
+ ioc: IOCContainerInterface,
91
+ _manager: IOCManagerInterface<IOCContainerInterface>
92
+ ): void {
93
+ this.registerGlobals(ioc);
94
+ this.registerCommon(ioc);
95
+ this.registerImplement(ioc);
96
+ }
97
+ }
@@ -0,0 +1,24 @@
1
+ // ! global variables, don't import any dependencies and don't have side effects
2
+ import { ColorFormatter, ConsoleHandler, Logger } from '@qlover/corekit-bridge';
3
+ import { JSONSerializer } from '@qlover/fe-corekit';
4
+ import { loggerStyles } from '@config/common';
5
+ import { AppConfig } from '@/base/cases/AppConfig';
6
+ import { DialogHandler } from '@/base/cases/DialogHandler';
7
+
8
+ export const appConfig = new AppConfig();
9
+
10
+ export const dialogHandler = new DialogHandler();
11
+
12
+ /**
13
+ * Global logger
14
+ */
15
+ export const logger = new Logger({
16
+ handlers: new ConsoleHandler(new ColorFormatter(loggerStyles)),
17
+ silent: false,
18
+ level: 'debug'
19
+ });
20
+
21
+ /**
22
+ * Override JSONSerializer to use the global logger
23
+ */
24
+ export const JSON = new JSONSerializer();
@@ -0,0 +1,52 @@
1
+ import {
2
+ createIOCFunction,
3
+ type IOCContainerInterface,
4
+ type IOCFunctionInterface
5
+ } from '@qlover/corekit-bridge';
6
+ import { AppConfig } from '@/base/cases/AppConfig';
7
+ import { InversifyContainer } from '@/base/cases/InversifyContainer';
8
+ import type { IOCInterface } from '@/base/port/IOCInterface';
9
+ import { ServerIOCRegister } from './ServerIOCRegister';
10
+ import type { IOCIdentifierMapServer } from '@config/IOCIdentifier';
11
+
12
+ export class ServerIOC
13
+ implements IOCInterface<IOCIdentifierMapServer, IOCContainerInterface>
14
+ {
15
+ static instance: ServerIOC | null = null;
16
+
17
+ protected ioc: IOCFunctionInterface<
18
+ IOCIdentifierMapServer,
19
+ IOCContainerInterface
20
+ > | null = null;
21
+
22
+ static create(): ServerIOC {
23
+ if (this.instance) {
24
+ return this.instance;
25
+ }
26
+
27
+ this.instance = new ServerIOC();
28
+
29
+ return this.instance;
30
+ }
31
+
32
+ create(): IOCFunctionInterface<
33
+ IOCIdentifierMapServer,
34
+ IOCContainerInterface
35
+ > {
36
+ if (this.ioc) {
37
+ return this.ioc;
38
+ }
39
+
40
+ this.ioc = createIOCFunction<IOCIdentifierMapServer>(
41
+ new InversifyContainer()
42
+ );
43
+
44
+ const register = new ServerIOCRegister({
45
+ appConfig: new AppConfig()
46
+ });
47
+
48
+ register.register(this.ioc.implemention!, this.ioc);
49
+
50
+ return this.ioc;
51
+ }
52
+ }
@@ -0,0 +1,63 @@
1
+ import {
2
+ ConsoleHandler,
3
+ Logger,
4
+ TimestampFormatter,
5
+ type IOCContainerInterface,
6
+ type IOCManagerInterface,
7
+ type IOCRegisterInterface
8
+ } from '@qlover/corekit-bridge';
9
+ import { IOCIdentifier as I } from '@config/IOCIdentifier';
10
+ import type { IocRegisterOptions } from '@/base/port/IOCInterface';
11
+
12
+ export class ServerIOCRegister
13
+ implements IOCRegisterInterface<IOCContainerInterface, IocRegisterOptions>
14
+ {
15
+ constructor(protected options: IocRegisterOptions) {}
16
+
17
+ /**
18
+ * Register globals
19
+ *
20
+ * 一般用于注册全局
21
+ *
22
+ * @param ioc - IOC container
23
+ */
24
+ protected registerGlobals(ioc: IOCContainerInterface): void {
25
+ const { appConfig } = this.options;
26
+ ioc.bind(I.AppConfig, appConfig);
27
+ ioc.bind(
28
+ I.Logger,
29
+ new Logger({
30
+ handlers: new ConsoleHandler(
31
+ new TimestampFormatter({
32
+ localeOptions: {
33
+ year: '2-digit',
34
+ month: '2-digit',
35
+ day: '2-digit',
36
+ hour: '2-digit',
37
+ minute: '2-digit',
38
+ second: '2-digit'
39
+ }
40
+ })
41
+ ),
42
+ silent: false,
43
+ level: appConfig.env === 'development' ? 'debug' : 'info'
44
+ })
45
+ );
46
+ }
47
+
48
+ protected registerImplement(_ioc: IOCContainerInterface): void {}
49
+
50
+ protected registerCommon(_ioc: IOCContainerInterface): void {}
51
+
52
+ /**
53
+ * @override
54
+ */
55
+ register(
56
+ ioc: IOCContainerInterface,
57
+ _manager: IOCManagerInterface<IOCContainerInterface>
58
+ ): void {
59
+ this.registerGlobals(ioc);
60
+ this.registerCommon(ioc);
61
+ this.registerImplement(ioc);
62
+ }
63
+ }
@@ -0,0 +1,21 @@
1
+ // src/i18n/request.ts
2
+
3
+ import { getRequestConfig } from 'next-intl/server';
4
+ import { routing, type Locale } from './routing';
5
+
6
+ // Export a function to configure next-intl on each request (server-side)
7
+ export default getRequestConfig(async ({ requestLocale }) => {
8
+ // The incoming requestLocale typically matches the `[locale]` URL segment
9
+ let locale = await requestLocale;
10
+
11
+ // Ensure a valid, supported locale is always used
12
+ if (!locale || !routing.locales.includes(locale as Locale)) {
13
+ locale = routing.defaultLocale;
14
+ }
15
+
16
+ // Dynamically import the translation messages for the selected locale
17
+ return {
18
+ locale,
19
+ messages: (await import(`../../public/locales/${locale}.json`)).default
20
+ };
21
+ });
@@ -0,0 +1,30 @@
1
+ import { createNavigation } from 'next-intl/navigation';
2
+ import { defineRouting } from 'next-intl/routing';
3
+ import { useLocaleRoutes } from '@config/common';
4
+ import { i18nConfig } from '@config/i18n';
5
+
6
+ const locales = i18nConfig.supportedLngs;
7
+
8
+ export type Locale = (typeof locales)[number];
9
+
10
+ export const routing = defineRouting({
11
+ locales,
12
+
13
+ defaultLocale: i18nConfig.fallbackLng,
14
+
15
+ localePrefix: useLocaleRoutes ? undefined : 'as-needed',
16
+
17
+ pathnames: {
18
+ '/': {
19
+ en: '/',
20
+ zh: '/'
21
+ },
22
+ '/login': {
23
+ en: '/login',
24
+ zh: '/login'
25
+ }
26
+ }
27
+ });
28
+
29
+ export const { Link, redirect, usePathname, useRouter, getPathname } =
30
+ createNavigation(routing);
@@ -0,0 +1,25 @@
1
+ // src/middleware.ts
2
+
3
+ // Import the Next.js middleware helper from next-intl
4
+ import createMiddleware from 'next-intl/middleware';
5
+
6
+ // Import your routing configuration which contains all locales, defaultLocale, and pathnames
7
+ import { routing } from './i18n/routing';
8
+
9
+ // Export the middleware created by next-intl
10
+ // This middleware will handle locale detection, redirects, and internationalized routing automatically
11
+ export default createMiddleware(routing);
12
+
13
+ // Next.js middleware configuration object
14
+ export const config = {
15
+ matcher: [
16
+ '/', // Match the root path explicitly
17
+
18
+ // Match all paths except for:
19
+ // - API routes
20
+ // - Next.js internals (_next/*)
21
+ // - Static files (*.svg, *.png, *.jpg, *.jpeg, *.gif, *.ico)
22
+ // - Other static assets and special files
23
+ '/((?!api|_next|.*\\.(?:svg|png|jpg|jpeg|gif|ico)|favicon.ico|sitemap.xml|sitemap-0.xml).*)'
24
+ ]
25
+ };