@payez/next-mvp 4.1.1 → 4.1.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.
@@ -1,167 +1,167 @@
1
- /**
2
- * Ready-to-Use Session Management Route
3
- *
4
- * Provides pre-configured session handlers for checking and updating session state.
5
- *
6
- * @example
7
- * ```typescript
8
- * // app/api/auth/session/route.ts
9
- * export { GET, POST } from '@payez/next-mvp/routes/auth/session';
10
- * ```
11
- *
12
- * @version 2.0.0
13
- * @since auth-ready-v2
14
- */
15
-
16
- import { NextRequest, NextResponse } from 'next/server';
17
- import { getSession as getBetterAuthSession } from '../../server/auth';
18
- import { getSession as getRedisSession, updateSession } from '../../lib/session-store';
19
-
20
- /**
21
- * GET /api/auth/session - Check current session status
22
- *
23
- * Returns the current session information including:
24
- * - User details
25
- * - Token expiry status
26
- * - Session validity
27
- */
28
- export async function GET(req: NextRequest) {
29
- try {
30
- const authSession = await getBetterAuthSession(req);
31
-
32
- if (!authSession) {
33
- console.warn('[SESSION_ROUTE] Better Auth session not found');
34
- // MUST return empty {} — useSession() treats any non-empty
35
- // response object as "authenticated", causing redirect loops on login page.
36
- return NextResponse.json({});
37
- }
38
-
39
- const redisSessionId = authSession.session?.token;
40
-
41
- console.log('[SESSION_ROUTE] Session found:', {
42
- userId: authSession.user?.id,
43
- email: authSession.user?.email,
44
- name: authSession.user?.name,
45
- redisSessionId: redisSessionId ? redisSessionId.substring(0, 8) + '...' : 'MISSING',
46
- });
47
-
48
- // Fetch full session data from Redis
49
- const session = redisSessionId ? await getRedisSession(redisSessionId) : null;
50
-
51
- console.log('[SESSION_ROUTE] Redis session:', {
52
- found: !!session,
53
- userId: session?.userId,
54
- roles: session?.roles,
55
- hasAccessToken: !!session?.idpAccessToken,
56
- });
57
-
58
- // Return session format with Redis data
59
- // useSession() expects: { user: {...}, expires: "..." }
60
- // We enrich with all session data from Redis
61
- return NextResponse.json({
62
- user: {
63
- id: session?.userId || authSession.user?.id,
64
- email: session?.email || authSession.user?.email,
65
- name: session?.name || authSession.user?.name,
66
- image: authSession.user?.image || null,
67
- // Redis session data
68
- roles: session?.roles || [],
69
- twoFactorSessionVerified: session?.mfaVerified || false,
70
- requiresTwoFactor: !session?.mfaVerified,
71
- authenticationMethods: session?.authenticationMethods,
72
- authenticationLevel: session?.authenticationLevel,
73
- mfaCompletedAt: session?.mfaCompletedAt,
74
- mfaExpiresAt: session?.mfaExpiresAt,
75
- mfaValidityHours: session?.mfaValidityHours,
76
- oauthProvider: session?.oauthProvider,
77
- idpClientId: session?.idpClientId,
78
- merchantId: session?.merchantId,
79
- },
80
- // Session tokens
81
- sessionToken: redisSessionId,
82
- accessToken: session?.idpAccessToken,
83
- refreshToken: session?.idpRefreshToken,
84
- accessTokenExpires: session?.idpAccessTokenExpires,
85
- expires: authSession.session?.expiresAt
86
- ? new Date(authSession.session.expiresAt).toISOString()
87
- : new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
88
- });
89
- } catch (error) {
90
- console.error('[SESSION_ROUTE] Error checking session:', error);
91
- return NextResponse.json({
92
- error: 'Failed to check session',
93
- details: error instanceof Error ? error.message : 'Unknown error'
94
- }, { status: 500 });
95
- }
96
- }
97
-
98
- /**
99
- * POST /api/auth/session - Update session data
100
- *
101
- * Allows updating session metadata (not tokens).
102
- * Token refresh should use the /api/auth/refresh endpoint.
103
- *
104
- * Body:
105
- * - metadata: object - Custom metadata to store in session
106
- */
107
- export async function POST(req: NextRequest) {
108
- try {
109
- const authSession = await getBetterAuthSession(req);
110
-
111
- if (!authSession) {
112
- return NextResponse.json({
113
- error: 'No session found',
114
- code: 'UNAUTHORIZED'
115
- }, { status: 401 });
116
- }
117
-
118
- const sessionToken = authSession.session?.token;
119
- if (!sessionToken) {
120
- return NextResponse.json({
121
- error: 'Invalid session',
122
- code: 'INVALID_SESSION'
123
- }, { status: 400 });
124
- }
125
-
126
- const body = await req.json();
127
- const { metadata, access_token, refresh_token, twoFactorComplete, twoFactorMethod } = body;
128
-
129
- // Get current session from Redis
130
- const session = await getRedisSession(sessionToken);
131
- if (!session) {
132
- return NextResponse.json({
133
- error: 'Session not found',
134
- code: 'SESSION_NOT_FOUND'
135
- }, { status: 404 });
136
- }
137
-
138
- // Update session with new data
139
- const updatedSession = {
140
- ...session,
141
- ...(access_token ? { accessToken: access_token } : {}),
142
- ...(refresh_token ? { refreshToken: refresh_token } : {}),
143
- ...(typeof twoFactorComplete === 'boolean' ? { twoFactorComplete } : {}),
144
- ...(twoFactorMethod ? { twoFactorMethod } : {}),
145
- ...(metadata ? {
146
- metadata: {
147
- ...(session.metadata || {}),
148
- ...metadata,
149
- updatedAt: new Date().toISOString()
150
- }
151
- } : {})
152
- };
153
-
154
- await updateSession(sessionToken, updatedSession);
155
-
156
- return NextResponse.json({
157
- success: true,
158
- message: 'Session updated successfully'
159
- });
160
- } catch (error) {
161
- console.error('[SESSION_ROUTE] Error updating session:', error);
162
- return NextResponse.json({
163
- error: 'Failed to update session',
164
- details: error instanceof Error ? error.message : 'Unknown error'
165
- }, { status: 500 });
166
- }
1
+ /**
2
+ * Ready-to-Use Session Management Route
3
+ *
4
+ * Provides pre-configured session handlers for checking and updating session state.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // app/api/auth/session/route.ts
9
+ * export { GET, POST } from '@payez/next-mvp/routes/auth/session';
10
+ * ```
11
+ *
12
+ * @version 2.0.0
13
+ * @since auth-ready-v2
14
+ */
15
+
16
+ import { NextRequest, NextResponse } from 'next/server';
17
+ import { getSession as getBetterAuthSession } from '../../server/auth';
18
+ import { getSession as getRedisSession, updateSession } from '../../lib/session-store';
19
+
20
+ /**
21
+ * GET /api/auth/session - Check current session status
22
+ *
23
+ * Returns the current session information including:
24
+ * - User details
25
+ * - Token expiry status
26
+ * - Session validity
27
+ */
28
+ export async function GET(req: NextRequest) {
29
+ try {
30
+ const authSession = await getBetterAuthSession(req);
31
+
32
+ if (!authSession) {
33
+ console.warn('[SESSION_ROUTE] Better Auth session not found');
34
+ // MUST return empty {} — useSession() treats any non-empty
35
+ // response object as "authenticated", causing redirect loops on login page.
36
+ return NextResponse.json({});
37
+ }
38
+
39
+ const redisSessionId = authSession.session?.token;
40
+
41
+ console.log('[SESSION_ROUTE] Session found:', {
42
+ userId: authSession.user?.id,
43
+ email: authSession.user?.email,
44
+ name: authSession.user?.name,
45
+ redisSessionId: redisSessionId ? redisSessionId.substring(0, 8) + '...' : 'MISSING',
46
+ });
47
+
48
+ // Fetch full session data from Redis
49
+ const session = redisSessionId ? await getRedisSession(redisSessionId) : null;
50
+
51
+ console.log('[SESSION_ROUTE] Redis session:', {
52
+ found: !!session,
53
+ userId: session?.userId,
54
+ roles: session?.roles,
55
+ hasAccessToken: !!session?.idpAccessToken,
56
+ });
57
+
58
+ // Return session format with Redis data
59
+ // useSession() expects: { user: {...}, expires: "..." }
60
+ // We enrich with all session data from Redis
61
+ return NextResponse.json({
62
+ user: {
63
+ id: session?.userId || authSession.user?.id,
64
+ email: session?.email || authSession.user?.email,
65
+ name: session?.name || authSession.user?.name,
66
+ image: authSession.user?.image || session?.image || null,
67
+ // Redis session data
68
+ roles: session?.roles || [],
69
+ twoFactorSessionVerified: session?.mfaVerified || false,
70
+ requiresTwoFactor: !session?.mfaVerified,
71
+ authenticationMethods: session?.authenticationMethods,
72
+ authenticationLevel: session?.authenticationLevel,
73
+ mfaCompletedAt: session?.mfaCompletedAt,
74
+ mfaExpiresAt: session?.mfaExpiresAt,
75
+ mfaValidityHours: session?.mfaValidityHours,
76
+ oauthProvider: session?.oauthProvider,
77
+ idpClientId: session?.idpClientId,
78
+ merchantId: session?.merchantId,
79
+ },
80
+ // Session tokens
81
+ sessionToken: redisSessionId,
82
+ accessToken: session?.idpAccessToken,
83
+ refreshToken: session?.idpRefreshToken,
84
+ accessTokenExpires: session?.idpAccessTokenExpires,
85
+ expires: authSession.session?.expiresAt
86
+ ? new Date(authSession.session.expiresAt).toISOString()
87
+ : new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
88
+ });
89
+ } catch (error) {
90
+ console.error('[SESSION_ROUTE] Error checking session:', error);
91
+ return NextResponse.json({
92
+ error: 'Failed to check session',
93
+ details: error instanceof Error ? error.message : 'Unknown error'
94
+ }, { status: 500 });
95
+ }
96
+ }
97
+
98
+ /**
99
+ * POST /api/auth/session - Update session data
100
+ *
101
+ * Allows updating session metadata (not tokens).
102
+ * Token refresh should use the /api/auth/refresh endpoint.
103
+ *
104
+ * Body:
105
+ * - metadata: object - Custom metadata to store in session
106
+ */
107
+ export async function POST(req: NextRequest) {
108
+ try {
109
+ const authSession = await getBetterAuthSession(req);
110
+
111
+ if (!authSession) {
112
+ return NextResponse.json({
113
+ error: 'No session found',
114
+ code: 'UNAUTHORIZED'
115
+ }, { status: 401 });
116
+ }
117
+
118
+ const sessionToken = authSession.session?.token;
119
+ if (!sessionToken) {
120
+ return NextResponse.json({
121
+ error: 'Invalid session',
122
+ code: 'INVALID_SESSION'
123
+ }, { status: 400 });
124
+ }
125
+
126
+ const body = await req.json();
127
+ const { metadata, access_token, refresh_token, twoFactorComplete, twoFactorMethod } = body;
128
+
129
+ // Get current session from Redis
130
+ const session = await getRedisSession(sessionToken);
131
+ if (!session) {
132
+ return NextResponse.json({
133
+ error: 'Session not found',
134
+ code: 'SESSION_NOT_FOUND'
135
+ }, { status: 404 });
136
+ }
137
+
138
+ // Update session with new data
139
+ const updatedSession = {
140
+ ...session,
141
+ ...(access_token ? { accessToken: access_token } : {}),
142
+ ...(refresh_token ? { refreshToken: refresh_token } : {}),
143
+ ...(typeof twoFactorComplete === 'boolean' ? { twoFactorComplete } : {}),
144
+ ...(twoFactorMethod ? { twoFactorMethod } : {}),
145
+ ...(metadata ? {
146
+ metadata: {
147
+ ...(session.metadata || {}),
148
+ ...metadata,
149
+ updatedAt: new Date().toISOString()
150
+ }
151
+ } : {})
152
+ };
153
+
154
+ await updateSession(sessionToken, updatedSession);
155
+
156
+ return NextResponse.json({
157
+ success: true,
158
+ message: 'Session updated successfully'
159
+ });
160
+ } catch (error) {
161
+ console.error('[SESSION_ROUTE] Error updating session:', error);
162
+ return NextResponse.json({
163
+ error: 'Failed to update session',
164
+ details: error instanceof Error ? error.message : 'Unknown error'
165
+ }, { status: 500 });
166
+ }
167
167
  }