@qlover/create-app 1.0.1 → 1.0.2
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 +15 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/next-app/config/Identifier/api.ts +7 -0
- package/dist/templates/next-app/config/Identifier/pages/page.register.ts +8 -0
- package/dist/templates/next-app/config/common.ts +1 -1
- package/dist/templates/next-app/config/i18n/HomeI18n.ts +2 -0
- package/dist/templates/next-app/config/i18n/register18n.ts +2 -1
- package/dist/templates/next-app/config/route.ts +9 -0
- package/dist/templates/next-app/migrations/schema/UserSchema.ts +1 -1
- package/dist/templates/next-app/next.config.ts +5 -4
- package/dist/templates/next-app/package.json +7 -8
- package/dist/templates/next-app/public/locales/en.json +4 -1
- package/dist/templates/next-app/public/locales/zh.json +4 -1
- package/dist/templates/next-app/src/app/[locale]/auth/layout.tsx +18 -0
- package/dist/templates/next-app/src/app/[locale]/{login → auth/login}/LoginForm.tsx +2 -1
- package/dist/templates/next-app/src/app/[locale]/{login → auth/login}/page.tsx +4 -5
- package/dist/templates/next-app/src/app/[locale]/auth/page.tsx +8 -0
- package/dist/templates/next-app/src/app/[locale]/{register → auth/register}/RegisterForm.tsx +24 -3
- package/dist/templates/next-app/src/app/[locale]/{register → auth/register}/page.tsx +4 -5
- package/dist/templates/next-app/src/app/[locale]/page.tsx +18 -45
- package/dist/templates/next-app/src/app/api/ai/completions/route.ts +13 -13
- package/dist/templates/next-app/src/app/api/auth/callback/route.ts +11 -0
- package/dist/templates/next-app/src/app/api/callback/route.ts +49 -0
- package/dist/templates/next-app/src/base/cases/AppConfig.ts +2 -0
- package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +3 -6
- package/dist/templates/next-app/src/base/cases/DialogHandler.ts +0 -1
- package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +13 -15
- package/dist/templates/next-app/src/base/cases/RouterService.ts +2 -7
- package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +0 -6
- package/dist/templates/next-app/src/base/cases/TranslateI18nUtil.ts +53 -0
- package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +0 -10
- package/dist/templates/next-app/src/base/port/AdminLayoutInterface.ts +0 -3
- package/dist/templates/next-app/src/base/port/AppUserApiInterface.ts +1 -1
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +0 -18
- package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +10 -5
- package/dist/templates/next-app/src/base/services/{appApi/AppApiRequester.ts → AppApiRequester.ts} +16 -11
- package/dist/templates/next-app/src/base/services/AppUserGateway.ts +110 -0
- package/dist/templates/next-app/src/base/services/I18nService.ts +1 -7
- package/dist/templates/next-app/src/base/services/ResourceService.ts +1 -4
- package/dist/templates/next-app/src/base/services/UserService.ts +28 -17
- package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +5 -7
- package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +4 -3
- package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +24 -16
- package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +2 -5
- package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +15 -18
- package/dist/templates/next-app/src/core/clientIoc/ClientIOCRegister.ts +0 -5
- package/dist/templates/next-app/src/core/globals.ts +1 -0
- package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +2 -8
- package/dist/templates/next-app/src/i18n/routing.ts +8 -3
- package/dist/templates/next-app/src/lib/supabase/client.ts +8 -0
- package/dist/templates/next-app/src/lib/supabase/conts.ts +2 -0
- package/dist/templates/next-app/src/lib/supabase/proxy.ts +84 -0
- package/dist/templates/next-app/src/lib/supabase/server.ts +38 -0
- package/dist/templates/next-app/src/proxy.ts +8 -1
- package/dist/templates/next-app/src/server/AppPageRouteParams.ts +5 -2
- package/dist/templates/next-app/src/server/NextApiServer.ts +2 -9
- package/dist/templates/next-app/src/server/PagesRouteParams.ts +3 -4
- package/dist/templates/next-app/src/server/ServerAuth.ts +18 -12
- package/dist/templates/next-app/src/server/SupabaseBridge.ts +66 -59
- package/dist/templates/next-app/src/server/controllers/UserController.ts +7 -2
- package/dist/templates/next-app/src/server/port/ServerAuthInterface.ts +4 -0
- package/dist/templates/next-app/src/server/port/ServerInterface.ts +2 -1
- package/dist/templates/next-app/src/server/port/UserServiceInterface.ts +7 -1
- package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +0 -3
- package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +0 -3
- package/dist/templates/next-app/src/server/services/UserService.ts +71 -51
- package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +0 -3
- package/dist/templates/next-app/src/server/validators/LoginValidator.ts +0 -6
- package/dist/templates/next-app/src/server/validators/SignupVerifyValidator.ts +68 -0
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +3 -3
- package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +0 -6
- package/dist/templates/next-app/src/uikit/components-app/AdminButton.tsx +29 -0
- package/dist/templates/next-app/src/uikit/components-app/AppRoutePage.tsx +21 -28
- package/dist/templates/next-app/src/uikit/components-app/AuthButton.tsx +20 -0
- package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +2 -2
- package/dist/templates/next-app/src/uikit/hook/useWarnTranslations.ts +3 -17
- package/dist/templates/next-app/src/uikit/utils/getHashParams.ts +8 -0
- package/dist/templates/next-app/src/uikit/utils/getHashVerifyEmailParams.ts +42 -0
- package/package.json +1 -1
- package/dist/templates/next-app/src/base/cases/TranslateI18nInterface.ts +0 -25
- package/dist/templates/next-app/src/base/cases/UserServiceApi.ts +0 -78
- package/dist/templates/next-app/src/base/services/adminApi/AdminApiRequester.ts +0 -25
- package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +0 -78
- package/dist/templates/next-app/src/server/port/UserControllerInerface.ts +0 -8
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExecutorError, isRequestAdapterResponse } from '@qlover/fe-corekit';
|
|
2
|
+
import type { AppApiErrorInterface } from '@/base/port/AppApiInterface';
|
|
3
|
+
import type { AppApiConfig } from '../AppApiRequester';
|
|
4
|
+
import type {
|
|
2
5
|
ExecutorContextInterface,
|
|
3
|
-
|
|
4
|
-
isRequestAdapterResponse,
|
|
6
|
+
HookRuntimes,
|
|
5
7
|
LifecyclePluginInterface
|
|
6
8
|
} from '@qlover/fe-corekit';
|
|
7
|
-
import type { AppApiErrorInterface } from '@/base/port/AppApiInterface';
|
|
8
|
-
import type { AppApiConfig } from './AppApiRequester';
|
|
9
9
|
import type { LoggerInterface } from '@qlover/logger';
|
|
10
10
|
|
|
11
11
|
export class AppApiPlugin implements LifecyclePluginInterface<
|
|
@@ -15,9 +15,6 @@ export class AppApiPlugin implements LifecyclePluginInterface<
|
|
|
15
15
|
|
|
16
16
|
constructor(protected logger: LoggerInterface) {}
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* @override
|
|
20
|
-
*/
|
|
21
18
|
public isAppApiErrorInterface(value: unknown): value is AppApiErrorInterface {
|
|
22
19
|
return (
|
|
23
20
|
typeof value === 'object' &&
|
|
@@ -29,6 +26,19 @@ export class AppApiPlugin implements LifecyclePluginInterface<
|
|
|
29
26
|
);
|
|
30
27
|
}
|
|
31
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @override
|
|
31
|
+
* @param ctx
|
|
32
|
+
*/
|
|
33
|
+
public onBefore(
|
|
34
|
+
ctx: ExecutorContextInterface<AppApiConfig<unknown>, unknown, HookRuntimes>
|
|
35
|
+
): void {
|
|
36
|
+
ctx.setParameters({
|
|
37
|
+
...ctx.parameters,
|
|
38
|
+
// TODO: ReqeustPlugin 在处理路径后会保留baseUrl,然后拼接 url,但是 fetchAdapter 会再次组合两个参数导致重复
|
|
39
|
+
baseURL: ''
|
|
40
|
+
});
|
|
41
|
+
}
|
|
32
42
|
/**
|
|
33
43
|
* @override
|
|
34
44
|
*/
|
|
@@ -39,7 +49,10 @@ export class AppApiPlugin implements LifecyclePluginInterface<
|
|
|
39
49
|
// Important: 当响应数据失败则抛出错误
|
|
40
50
|
if (isRequestAdapterResponse(response)) {
|
|
41
51
|
if (this.isAppApiErrorInterface(response.data)) {
|
|
42
|
-
throw new ExecutorError(
|
|
52
|
+
throw new ExecutorError(
|
|
53
|
+
response.data.message || response.data.id,
|
|
54
|
+
response
|
|
55
|
+
);
|
|
43
56
|
}
|
|
44
57
|
}
|
|
45
58
|
|
|
@@ -77,9 +90,6 @@ export class AppApiPlugin implements LifecyclePluginInterface<
|
|
|
77
90
|
}
|
|
78
91
|
}
|
|
79
92
|
|
|
80
|
-
/**
|
|
81
|
-
* @override
|
|
82
|
-
*/
|
|
83
93
|
protected async getResponseJson(response: Response): Promise<unknown> {
|
|
84
94
|
try {
|
|
85
95
|
return await response.json();
|
|
@@ -88,15 +98,13 @@ export class AppApiPlugin implements LifecyclePluginInterface<
|
|
|
88
98
|
}
|
|
89
99
|
}
|
|
90
100
|
|
|
91
|
-
/**
|
|
92
|
-
* @override
|
|
93
|
-
*/
|
|
94
101
|
protected loggerError(config: AppApiConfig, error: unknown): void {
|
|
95
102
|
this.logger.error(
|
|
96
103
|
`%c[AppApi ${config.method} ${config.url}]%c - ${new Date().toLocaleString()}`,
|
|
97
104
|
'color: #f00;',
|
|
98
105
|
'color: inherit;',
|
|
99
|
-
error
|
|
106
|
+
error,
|
|
107
|
+
config
|
|
100
108
|
);
|
|
101
109
|
}
|
|
102
110
|
}
|
|
@@ -4,8 +4,8 @@ import { RequestEncryptPlugin } from '@/base/cases/RequestEncryptPlugin';
|
|
|
4
4
|
import { StringEncryptor } from '@/base/cases/StringEncryptor';
|
|
5
5
|
import { I } from '@config/IOCIdentifier';
|
|
6
6
|
import { AppApiPlugin } from './AppApiPlugin';
|
|
7
|
-
import { AppApiRequester } from '
|
|
8
|
-
import type { AppApiConfig } from '
|
|
7
|
+
import { AppApiRequester } from '../AppApiRequester';
|
|
8
|
+
import type { AppApiConfig } from '../AppApiRequester';
|
|
9
9
|
import type {
|
|
10
10
|
BootstrapContext,
|
|
11
11
|
BootstrapExecutorPlugin
|
|
@@ -35,9 +35,6 @@ export class AppUserApiBootstrap implements BootstrapExecutorPlugin {
|
|
|
35
35
|
appUserApi.use(ioc.get(DialogErrorPlugin));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/**
|
|
39
|
-
* @override
|
|
40
|
-
*/
|
|
41
38
|
protected requestDataSerializer(
|
|
42
39
|
data: unknown,
|
|
43
40
|
config: AppApiConfig
|
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { LifecycleExecutor } from '@qlover/fe-corekit';
|
|
3
|
+
import type { ServerInterface } from '@/server/port/ServerInterface';
|
|
4
|
+
import { I, type IOCIdentifierMapServer } from '@config/IOCIdentifier';
|
|
5
|
+
import { ServerIOC } from '../serverIoc/ServerIOC';
|
|
6
|
+
import type {
|
|
7
|
+
ServiceIdentifier,
|
|
8
|
+
IOCContainerInterface,
|
|
9
|
+
IOCFunctionInterface,
|
|
6
10
|
BootstrapPluginOptions
|
|
7
11
|
} from '@qlover/corekit-bridge';
|
|
8
|
-
import {
|
|
12
|
+
import type {
|
|
13
|
+
ExecutorError,
|
|
9
14
|
ExecutorAsyncTask,
|
|
10
15
|
ExecutorContextInterface,
|
|
11
|
-
|
|
12
|
-
LifecyclePluginInterface,
|
|
13
|
-
type ExecutorError
|
|
16
|
+
LifecyclePluginInterface
|
|
14
17
|
} from '@qlover/fe-corekit';
|
|
15
|
-
import type { ServerInterface } from '@/server/port/ServerInterface';
|
|
16
|
-
import { I, type IOCIdentifierMapServer } from '@config/IOCIdentifier';
|
|
17
|
-
import { ServerIOC } from '../serverIoc/ServerIOC';
|
|
18
18
|
import type { LoggerInterface } from '@qlover/logger';
|
|
19
19
|
|
|
20
20
|
export interface BootstrapServerContextOptions extends BootstrapPluginOptions {
|
|
21
21
|
IOC: IOCFunctionInterface<IOCIdentifierMapServer, IOCContainerInterface>;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export interface BootstrapServerPlugin
|
|
25
|
-
extends LifecyclePluginInterface<BootstrapServerContext> {}
|
|
24
|
+
export interface BootstrapServerPlugin extends LifecyclePluginInterface<BootstrapServerContext> {}
|
|
26
25
|
|
|
27
|
-
export interface BootstrapServerContext
|
|
28
|
-
extends ExecutorContextInterface<BootstrapServerContextOptions> {}
|
|
26
|
+
export interface BootstrapServerContext extends ExecutorContextInterface<BootstrapServerContextOptions> {}
|
|
29
27
|
|
|
30
28
|
export class BootstrapServer implements ServerInterface {
|
|
31
29
|
protected executor: LifecycleExecutor<
|
|
@@ -80,9 +78,6 @@ export class BootstrapServer implements ServerInterface {
|
|
|
80
78
|
return this.IOC(identifier);
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
/**
|
|
84
|
-
* @override
|
|
85
|
-
*/
|
|
86
81
|
public use(
|
|
87
82
|
plugin:
|
|
88
83
|
| BootstrapServerPlugin
|
|
@@ -126,3 +121,5 @@ export class BootstrapServer implements ServerInterface {
|
|
|
126
121
|
);
|
|
127
122
|
}
|
|
128
123
|
}
|
|
124
|
+
|
|
125
|
+
export const bootstrapServer = new BootstrapServer();
|
|
@@ -23,7 +23,6 @@ export class ClientIOCRegister implements IOCRegisterInterface<
|
|
|
23
23
|
*
|
|
24
24
|
* 一般用于注册全局
|
|
25
25
|
*
|
|
26
|
-
* @override
|
|
27
26
|
* @param ioc - IOC container
|
|
28
27
|
*/
|
|
29
28
|
protected registerGlobals(ioc: IOCContainerInterface): void {
|
|
@@ -48,7 +47,6 @@ export class ClientIOCRegister implements IOCRegisterInterface<
|
|
|
48
47
|
* - 国际化服务
|
|
49
48
|
* - 主题服务
|
|
50
49
|
*
|
|
51
|
-
* @override
|
|
52
50
|
* @param ioc
|
|
53
51
|
*/
|
|
54
52
|
protected registerImplement(ioc: IOCContainerInterface): void {
|
|
@@ -70,9 +68,6 @@ export class ClientIOCRegister implements IOCRegisterInterface<
|
|
|
70
68
|
// ioc.bind(I.RequestPageBridgeInterface, ioc.get(RequestPageBridge));
|
|
71
69
|
}
|
|
72
70
|
|
|
73
|
-
/**
|
|
74
|
-
* @override
|
|
75
|
-
*/
|
|
76
71
|
protected registerCommon(_ioc: IOCContainerInterface): void {
|
|
77
72
|
// const { appConfig } = this.options;
|
|
78
73
|
// const logger = ioc.get(I.Logger);
|
|
@@ -19,7 +19,6 @@ export class ServerIOCRegister implements IOCRegisterInterface<
|
|
|
19
19
|
*
|
|
20
20
|
* 一般用于注册全局
|
|
21
21
|
*
|
|
22
|
-
* @override
|
|
23
22
|
* @param ioc - IOC container
|
|
24
23
|
*/
|
|
25
24
|
protected registerGlobals(ioc: IOCContainerInterface): void {
|
|
@@ -28,6 +27,7 @@ export class ServerIOCRegister implements IOCRegisterInterface<
|
|
|
28
27
|
ioc.bind(
|
|
29
28
|
I.Logger,
|
|
30
29
|
new Logger({
|
|
30
|
+
name: 'next-app-server',
|
|
31
31
|
handlers: new ConsoleHandler(
|
|
32
32
|
new TimestampFormatter({
|
|
33
33
|
localeOptions: {
|
|
@@ -41,21 +41,15 @@ export class ServerIOCRegister implements IOCRegisterInterface<
|
|
|
41
41
|
})
|
|
42
42
|
),
|
|
43
43
|
silent: false,
|
|
44
|
-
level: appConfig.
|
|
44
|
+
level: appConfig.isProduction ? 'warn' : 'debug'
|
|
45
45
|
})
|
|
46
46
|
);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
/**
|
|
50
|
-
* @override
|
|
51
|
-
*/
|
|
52
49
|
protected registerImplement(ioc: IOCContainerInterface): void {
|
|
53
50
|
ioc.bind(I.DBBridgeInterface, ioc.get(SupabaseBridge));
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
/**
|
|
57
|
-
* @override
|
|
58
|
-
*/
|
|
59
53
|
protected registerCommon(_ioc: IOCContainerInterface): void {}
|
|
60
54
|
|
|
61
55
|
/**
|
|
@@ -2,6 +2,7 @@ import { createNavigation } from 'next-intl/navigation';
|
|
|
2
2
|
import { defineRouting } from 'next-intl/routing';
|
|
3
3
|
import { useLocaleRoutes } from '@config/common';
|
|
4
4
|
import { i18nConfig } from '@config/i18n';
|
|
5
|
+
import { ROUTE_LOGIN, ROUTE_REGISTER } from '@config/route';
|
|
5
6
|
|
|
6
7
|
const locales = i18nConfig.supportedLngs;
|
|
7
8
|
|
|
@@ -19,9 +20,13 @@ export const routing = defineRouting({
|
|
|
19
20
|
en: '/',
|
|
20
21
|
zh: '/'
|
|
21
22
|
},
|
|
22
|
-
|
|
23
|
-
en: '/login',
|
|
24
|
-
zh: '/login'
|
|
23
|
+
[ROUTE_LOGIN]: {
|
|
24
|
+
en: '/auth/login',
|
|
25
|
+
zh: '/auth/login'
|
|
26
|
+
},
|
|
27
|
+
[ROUTE_REGISTER]: {
|
|
28
|
+
en: '/auth/register',
|
|
29
|
+
zh: '/auth/register'
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
32
|
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createServerClient } from '@supabase/ssr';
|
|
2
|
+
import { NextResponse, type NextRequest } from 'next/server';
|
|
3
|
+
import { ROUTE_LOGIN, ROUTE_REGISTER } from '@config/route';
|
|
4
|
+
import { SUPABASE_KEY, SUPABASE_URL } from './conts';
|
|
5
|
+
|
|
6
|
+
export async function updateSession(request: NextRequest) {
|
|
7
|
+
let supabaseResponse = NextResponse.next({
|
|
8
|
+
request
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// If the env vars are not set, skip proxy check. You can remove this
|
|
12
|
+
// once you setup the project.
|
|
13
|
+
if (!SUPABASE_URL && SUPABASE_KEY) {
|
|
14
|
+
return supabaseResponse;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// With Fluid compute, don't put this client in a global environment
|
|
18
|
+
// variable. Always create a new one on each request.
|
|
19
|
+
const supabase = createServerClient(SUPABASE_URL!, SUPABASE_KEY!, {
|
|
20
|
+
// global: {
|
|
21
|
+
// fetch: (input, init) => {
|
|
22
|
+
// console.log('proxy supabase globals fetch', input, init);
|
|
23
|
+
|
|
24
|
+
// return fetch(input, init);
|
|
25
|
+
// }
|
|
26
|
+
// },
|
|
27
|
+
cookies: {
|
|
28
|
+
getAll() {
|
|
29
|
+
return request.cookies.getAll();
|
|
30
|
+
},
|
|
31
|
+
setAll(cookiesToSet) {
|
|
32
|
+
cookiesToSet.forEach(({ name, value }) =>
|
|
33
|
+
request.cookies.set(name, value)
|
|
34
|
+
);
|
|
35
|
+
supabaseResponse = NextResponse.next({
|
|
36
|
+
request
|
|
37
|
+
});
|
|
38
|
+
cookiesToSet.forEach(({ name, value, options }) =>
|
|
39
|
+
supabaseResponse.cookies.set(name, value, options)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Do not run code between createServerClient and
|
|
46
|
+
// supabase.auth.getClaims(). A simple mistake could make it very hard to debug
|
|
47
|
+
// issues with users being randomly logged out.
|
|
48
|
+
|
|
49
|
+
// IMPORTANT: If you remove getClaims() and you use server-side rendering
|
|
50
|
+
// with the Supabase client, your users may be randomly logged out.
|
|
51
|
+
const { data } = await supabase.auth.getClaims();
|
|
52
|
+
const user = data?.claims;
|
|
53
|
+
|
|
54
|
+
console.log('Proxy(supabase) logged?:', !!user);
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
request.nextUrl.pathname !== '/' &&
|
|
58
|
+
!user &&
|
|
59
|
+
!request.nextUrl.pathname.includes(ROUTE_LOGIN) &&
|
|
60
|
+
!request.nextUrl.pathname.includes(ROUTE_REGISTER)
|
|
61
|
+
) {
|
|
62
|
+
console.log('proxy supabase no user to login');
|
|
63
|
+
|
|
64
|
+
// no user, potentially respond by redirecting the user to the login page
|
|
65
|
+
const url = request.nextUrl.clone();
|
|
66
|
+
url.pathname = ROUTE_LOGIN;
|
|
67
|
+
return NextResponse.redirect(url);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// IMPORTANT: You *must* return the supabaseResponse object as it is.
|
|
71
|
+
// If you're creating a new response object with NextResponse.next() make sure to:
|
|
72
|
+
// 1. Pass the request in it, like so:
|
|
73
|
+
// const myNewResponse = NextResponse.next({ request })
|
|
74
|
+
// 2. Copy over the cookies, like so:
|
|
75
|
+
// myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
|
|
76
|
+
// 3. Change the myNewResponse object to fit your needs, but avoid changing
|
|
77
|
+
// the cookies!
|
|
78
|
+
// 4. Finally:
|
|
79
|
+
// return myNewResponse
|
|
80
|
+
// If this is not done, you may be causing the browser and server to go out
|
|
81
|
+
// of sync and terminate the user's session prematurely!
|
|
82
|
+
|
|
83
|
+
return supabaseResponse;
|
|
84
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createServerClient } from '@supabase/ssr';
|
|
2
|
+
import { cookies } from 'next/headers';
|
|
3
|
+
import { SUPABASE_KEY, SUPABASE_URL } from './conts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Especially important if using Fluid compute: Don't put this client in a
|
|
7
|
+
* global variable. Always create a new client within each function when using
|
|
8
|
+
* it.
|
|
9
|
+
*/
|
|
10
|
+
export async function createClient() {
|
|
11
|
+
const cookieStore = await cookies();
|
|
12
|
+
|
|
13
|
+
return createServerClient(SUPABASE_URL!, SUPABASE_KEY!, {
|
|
14
|
+
// global: {
|
|
15
|
+
// fetch: (input, init) => {
|
|
16
|
+
// console.log('supabase globals fetch', input, init);
|
|
17
|
+
|
|
18
|
+
// return fetch(input, init);
|
|
19
|
+
// }
|
|
20
|
+
// },
|
|
21
|
+
cookies: {
|
|
22
|
+
getAll() {
|
|
23
|
+
return cookieStore.getAll();
|
|
24
|
+
},
|
|
25
|
+
setAll(cookiesToSet) {
|
|
26
|
+
try {
|
|
27
|
+
cookiesToSet.forEach(({ name, value, options }) =>
|
|
28
|
+
cookieStore.set(name, value, options)
|
|
29
|
+
);
|
|
30
|
+
} catch {
|
|
31
|
+
// The `setAll` method was called from a Server Component.
|
|
32
|
+
// This can be ignored if you have proxy refreshing
|
|
33
|
+
// user sessions.
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -5,10 +5,17 @@ import createMiddleware from 'next-intl/middleware';
|
|
|
5
5
|
|
|
6
6
|
// Import your routing configuration which contains all locales, defaultLocale, and pathnames
|
|
7
7
|
import { routing } from './i18n/routing';
|
|
8
|
+
import { updateSession } from './lib/supabase/proxy';
|
|
9
|
+
import type { NextRequest } from 'next/server';
|
|
8
10
|
|
|
9
11
|
// Export the middleware created by next-intl
|
|
10
12
|
// This middleware will handle locale detection, redirects, and internationalized routing automatically
|
|
11
|
-
export default createMiddleware(routing);
|
|
13
|
+
// export default createMiddleware(routing);
|
|
14
|
+
|
|
15
|
+
export default async function proxy(request: NextRequest) {
|
|
16
|
+
await updateSession(request);
|
|
17
|
+
return createMiddleware(routing)(request);
|
|
18
|
+
}
|
|
12
19
|
|
|
13
20
|
// Next.js middleware configuration object
|
|
14
21
|
export const config = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cookies } from 'next/headers';
|
|
2
2
|
import { notFound } from 'next/navigation';
|
|
3
3
|
import { getMessages, getTranslations } from 'next-intl/server';
|
|
4
|
-
import {
|
|
4
|
+
import { TranslateI18nUtil } from '@/base/cases/TranslateI18nUtil';
|
|
5
5
|
import { filterMessagesByNamespace } from '@/i18n/loadMessages';
|
|
6
6
|
import { i18nConfig } from '@config/i18n';
|
|
7
7
|
import type { LocaleType, PageI18nInterface } from '@config/i18n';
|
|
@@ -91,7 +91,10 @@ export class AppPageRouteParams<
|
|
|
91
91
|
// namespace: namespace
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
return
|
|
94
|
+
return TranslateI18nUtil.translate<T>(
|
|
95
|
+
i18nInterface,
|
|
96
|
+
TranslateI18nUtil.overrideTranslateT(t)
|
|
97
|
+
);
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
/**
|
|
@@ -12,16 +12,10 @@ import { AppSuccessApi } from './AppSuccessApi';
|
|
|
12
12
|
import type { ExecutorAsyncTask } from '@qlover/fe-corekit';
|
|
13
13
|
|
|
14
14
|
export class NextApiServer extends BootstrapServer {
|
|
15
|
-
/**
|
|
16
|
-
* @override
|
|
17
|
-
*/
|
|
18
15
|
protected isAppApiResult(result: unknown): result is AppApiResult {
|
|
19
16
|
return isAppApiSuccessInterface(result) || isAppApiErrorInterface(result);
|
|
20
17
|
}
|
|
21
18
|
|
|
22
|
-
/**
|
|
23
|
-
* @override
|
|
24
|
-
*/
|
|
25
19
|
public async run<Result>(
|
|
26
20
|
task?: ExecutorAsyncTask<
|
|
27
21
|
Result | AppApiResult,
|
|
@@ -37,20 +31,19 @@ export class NextApiServer extends BootstrapServer {
|
|
|
37
31
|
|
|
38
32
|
// If result is ExecutorError, return AppErrorApi
|
|
39
33
|
if (result instanceof ExecutorError) {
|
|
34
|
+
this.logger.debug('NextApiServer run error:', result);
|
|
40
35
|
return new AppErrorApi(result.id, result.message);
|
|
41
36
|
}
|
|
42
37
|
|
|
43
38
|
// If result is Error, return AppErrorApi
|
|
44
39
|
if (result instanceof Error) {
|
|
40
|
+
this.logger.debug('NextApiServer run error:', result);
|
|
45
41
|
return new AppErrorApi('SERVER_ERROR', result.message);
|
|
46
42
|
}
|
|
47
43
|
|
|
48
44
|
return new AppSuccessApi(result);
|
|
49
45
|
}
|
|
50
46
|
|
|
51
|
-
/**
|
|
52
|
-
* @override
|
|
53
|
-
*/
|
|
54
47
|
public async runWithJson<Result>(
|
|
55
48
|
task?: ExecutorAsyncTask<
|
|
56
49
|
Result | AppApiResult,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TranslateI18nUtil } from '@/base/cases/TranslateI18nUtil';
|
|
2
2
|
import { loadMessages } from '@/i18n/loadMessages';
|
|
3
3
|
import { i18nConfig } from '@config/i18n';
|
|
4
4
|
import type { LocaleType, PageI18nInterface } from '@config/i18n';
|
|
@@ -100,9 +100,8 @@ export class PagesRouteParams implements RouteParamsnHandlerInterface {
|
|
|
100
100
|
/**
|
|
101
101
|
* 获取翻译后的 i18n 接口
|
|
102
102
|
* 创建一个简单的翻译函数,基于加载的 messages
|
|
103
|
-
|
|
104
103
|
* @override
|
|
105
|
-
|
|
104
|
+
*/
|
|
106
105
|
public async getI18nInterface<T extends PageI18nInterface>(
|
|
107
106
|
i18nInterface: T,
|
|
108
107
|
namespace?: string
|
|
@@ -131,7 +130,7 @@ export class PagesRouteParams implements RouteParamsnHandlerInterface {
|
|
|
131
130
|
return message;
|
|
132
131
|
};
|
|
133
132
|
|
|
134
|
-
return
|
|
133
|
+
return TranslateI18nUtil.translate<T>(
|
|
135
134
|
i18nInterface,
|
|
136
135
|
t as ReturnType<typeof useTranslations>
|
|
137
136
|
);
|
|
@@ -2,8 +2,10 @@ import { ExecutorError } from '@qlover/fe-corekit';
|
|
|
2
2
|
import { inject, injectable } from 'inversify';
|
|
3
3
|
import { cookies } from 'next/headers';
|
|
4
4
|
import type { AppConfig } from '@/base/cases/AppConfig';
|
|
5
|
+
import { UserSchema } from '@migrations/schema/UserSchema';
|
|
5
6
|
import { API_NOT_AUTHORIZED } from '@config/Identifier';
|
|
6
7
|
import { I } from '@config/IOCIdentifier';
|
|
8
|
+
import { SupabaseBridge } from './SupabaseBridge';
|
|
7
9
|
import { UserCredentialToken } from './UserCredentialToken';
|
|
8
10
|
import type { ServerAuthInterface } from './port/ServerAuthInterface';
|
|
9
11
|
|
|
@@ -13,7 +15,8 @@ export class ServerAuth implements ServerAuthInterface {
|
|
|
13
15
|
constructor(
|
|
14
16
|
@inject(I.AppConfig) protected server: AppConfig,
|
|
15
17
|
@inject(UserCredentialToken)
|
|
16
|
-
protected userCredentialToken: UserCredentialToken
|
|
18
|
+
protected userCredentialToken: UserCredentialToken,
|
|
19
|
+
@inject(SupabaseBridge) protected supabase: SupabaseBridge
|
|
17
20
|
) {
|
|
18
21
|
this.userTokenKey = server.userTokenKey;
|
|
19
22
|
}
|
|
@@ -31,19 +34,11 @@ export class ServerAuth implements ServerAuthInterface {
|
|
|
31
34
|
* @override
|
|
32
35
|
*/
|
|
33
36
|
public async hasAuth(): Promise<boolean> {
|
|
34
|
-
const
|
|
37
|
+
const supabase = await this.supabase.getSupabase();
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
const user = await this.userCredentialToken.parseToken(token);
|
|
39
|
+
const { data } = await supabase.auth.getClaims();
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
} catch {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
41
|
+
return !!data?.claims;
|
|
47
42
|
}
|
|
48
43
|
|
|
49
44
|
/**
|
|
@@ -72,4 +67,15 @@ export class ServerAuth implements ServerAuthInterface {
|
|
|
72
67
|
throw new ExecutorError(API_NOT_AUTHORIZED, 'Not authorized');
|
|
73
68
|
}
|
|
74
69
|
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @override
|
|
73
|
+
*/
|
|
74
|
+
public async getUser(): Promise<UserSchema | null> {
|
|
75
|
+
const supabase = await this.supabase.getSupabase();
|
|
76
|
+
|
|
77
|
+
const { data } = await supabase.auth.getUser();
|
|
78
|
+
|
|
79
|
+
return data.user ? this.supabase.toUserSchema(data.user) : null;
|
|
80
|
+
}
|
|
75
81
|
}
|