@payez/next-mvp 3.9.0 → 4.0.0

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 (149) hide show
  1. package/dist/api/auth-handler.d.ts +1 -2
  2. package/dist/api/auth-handler.js +9 -9
  3. package/dist/api-handlers/account/change-password.js +110 -112
  4. package/dist/api-handlers/admin/analytics.d.ts +19 -20
  5. package/dist/api-handlers/admin/analytics.js +378 -379
  6. package/dist/api-handlers/admin/audit.d.ts +19 -20
  7. package/dist/api-handlers/admin/audit.js +213 -214
  8. package/dist/api-handlers/admin/index.d.ts +21 -22
  9. package/dist/api-handlers/admin/index.js +42 -43
  10. package/dist/api-handlers/admin/redis-sessions.d.ts +35 -36
  11. package/dist/api-handlers/admin/redis-sessions.js +203 -204
  12. package/dist/api-handlers/admin/sessions.d.ts +20 -21
  13. package/dist/api-handlers/admin/sessions.js +283 -284
  14. package/dist/api-handlers/admin/site-logs.d.ts +45 -46
  15. package/dist/api-handlers/admin/site-logs.js +317 -318
  16. package/dist/api-handlers/admin/stats.d.ts +20 -21
  17. package/dist/api-handlers/admin/stats.js +239 -240
  18. package/dist/api-handlers/admin/users.d.ts +19 -20
  19. package/dist/api-handlers/admin/users.js +221 -222
  20. package/dist/api-handlers/admin/vibe-data.d.ts +79 -80
  21. package/dist/api-handlers/admin/vibe-data.js +267 -268
  22. package/dist/api-handlers/auth/refresh.js +633 -635
  23. package/dist/api-handlers/auth/signout.js +186 -187
  24. package/dist/api-handlers/auth/status.js +4 -7
  25. package/dist/api-handlers/auth/update-session.d.ts +1 -1
  26. package/dist/api-handlers/auth/update-session.js +12 -14
  27. package/dist/api-handlers/auth/verify-code.d.ts +43 -43
  28. package/dist/api-handlers/auth/verify-code.js +90 -94
  29. package/dist/api-handlers/session/viability.js +114 -146
  30. package/dist/api-handlers/test/force-expire.js +59 -65
  31. package/dist/auth/auth-decision.js +182 -182
  32. package/dist/auth/better-auth.d.ts +3 -6
  33. package/dist/auth/better-auth.js +3 -6
  34. package/dist/auth/route-config.js +2 -2
  35. package/dist/auth/utils/token-utils.d.ts +83 -84
  36. package/dist/auth/utils/token-utils.js +218 -219
  37. package/dist/client/AuthContext.js +115 -112
  38. package/dist/client/better-auth-client.d.ts +1020 -961
  39. package/dist/client/better-auth-client.js +54 -7
  40. package/dist/client/fetch-with-auth.js +2 -2
  41. package/dist/components/SessionSync.js +121 -119
  42. package/dist/components/account/MobileNavDrawer.js +64 -64
  43. package/dist/components/account/UserAvatarMenu.js +91 -88
  44. package/dist/components/admin/VibeAdminLayout.js +71 -69
  45. package/dist/hooks/useAuth.js +9 -7
  46. package/dist/hooks/useAuthSettings.js +93 -93
  47. package/dist/hooks/useAvailableProviders.d.ts +43 -45
  48. package/dist/hooks/useAvailableProviders.js +112 -108
  49. package/dist/hooks/useSessionExpiration.d.ts +2 -3
  50. package/dist/hooks/useSessionExpiration.js +2 -2
  51. package/dist/hooks/useViabilitySession.js +3 -2
  52. package/dist/index.js +4 -6
  53. package/dist/lib/app-slug.d.ts +95 -95
  54. package/dist/lib/app-slug.js +172 -172
  55. package/dist/lib/standardized-client-api.js +10 -5
  56. package/dist/lib/startup-init.js +21 -25
  57. package/dist/lib/test-aware-get-token.js +86 -81
  58. package/dist/lib/token-lifecycle.d.ts +78 -52
  59. package/dist/lib/token-lifecycle.js +360 -398
  60. package/dist/pages/admin-login/page.js +73 -83
  61. package/dist/pages/client-admin/ClientSiteAdminPage.js +179 -177
  62. package/dist/pages/login/page.js +202 -211
  63. package/dist/pages/showcase/ShowcasePage.js +142 -140
  64. package/dist/pages/test-env/EmergencyLogoutPage.js +99 -98
  65. package/dist/pages/test-env/JwtInspectPage.js +116 -114
  66. package/dist/pages/test-env/RefreshTokenPage.js +4 -2
  67. package/dist/pages/test-env/TestEnvPage.js +51 -49
  68. package/dist/pages/verify-code/page.js +412 -408
  69. package/dist/routes/auth/logout.d.ts +31 -31
  70. package/dist/routes/auth/logout.js +98 -113
  71. package/dist/routes/auth/nextauth.d.ts +14 -11
  72. package/dist/routes/auth/nextauth.js +25 -57
  73. package/dist/routes/auth/session.js +157 -179
  74. package/dist/routes/auth/viability.js +190 -201
  75. package/dist/server/auth.d.ts +50 -0
  76. package/dist/server/auth.js +62 -0
  77. package/dist/stores/authStore.js +19 -23
  78. package/dist/utils/logout.js +5 -5
  79. package/package.json +1 -3
  80. package/src/api/auth-handler.ts +550 -549
  81. package/src/api-handlers/account/change-password.ts +5 -8
  82. package/src/api-handlers/admin/analytics.ts +4 -6
  83. package/src/api-handlers/admin/audit.ts +5 -7
  84. package/src/api-handlers/admin/index.ts +1 -2
  85. package/src/api-handlers/admin/redis-sessions.ts +6 -8
  86. package/src/api-handlers/admin/sessions.ts +5 -7
  87. package/src/api-handlers/admin/site-logs.ts +8 -10
  88. package/src/api-handlers/admin/stats.ts +4 -6
  89. package/src/api-handlers/admin/users.ts +5 -7
  90. package/src/api-handlers/admin/vibe-data.ts +10 -12
  91. package/src/api-handlers/auth/refresh.ts +5 -7
  92. package/src/api-handlers/auth/signout.ts +5 -6
  93. package/src/api-handlers/auth/status.ts +4 -7
  94. package/src/api-handlers/auth/update-session.ts +123 -125
  95. package/src/api-handlers/auth/verify-code.ts +9 -13
  96. package/src/api-handlers/session/viability.ts +10 -47
  97. package/src/api-handlers/test/force-expire.ts +4 -11
  98. package/src/auth/auth-decision.ts +1 -1
  99. package/src/auth/better-auth.ts +138 -141
  100. package/src/auth/route-config.ts +219 -219
  101. package/src/auth/utils/token-utils.ts +0 -1
  102. package/src/client/AuthContext.tsx +6 -2
  103. package/src/client/better-auth-client.ts +54 -7
  104. package/src/client/fetch-with-auth.ts +47 -47
  105. package/src/components/SessionSync.tsx +6 -5
  106. package/src/components/account/MobileNavDrawer.tsx +3 -3
  107. package/src/components/account/UserAvatarMenu.tsx +6 -3
  108. package/src/components/admin/VibeAdminLayout.tsx +4 -2
  109. package/src/config/logger.ts +1 -1
  110. package/src/hooks/useAuth.ts +117 -115
  111. package/src/hooks/useAuthSettings.ts +2 -2
  112. package/src/hooks/useAvailableProviders.ts +9 -5
  113. package/src/hooks/useSessionExpiration.ts +101 -102
  114. package/src/hooks/useViabilitySession.ts +336 -335
  115. package/src/index.ts +60 -63
  116. package/src/lib/api-handler.ts +0 -1
  117. package/src/lib/app-slug.ts +6 -6
  118. package/src/lib/standardized-client-api.ts +901 -895
  119. package/src/lib/startup-init.ts +243 -247
  120. package/src/lib/test-aware-get-token.ts +22 -12
  121. package/src/lib/token-lifecycle.ts +12 -53
  122. package/src/pages/admin-login/page.tsx +9 -17
  123. package/src/pages/client-admin/ClientSiteAdminPage.tsx +4 -2
  124. package/src/pages/login/page.tsx +21 -28
  125. package/src/pages/showcase/ShowcasePage.tsx +4 -2
  126. package/src/pages/test-env/EmergencyLogoutPage.tsx +7 -6
  127. package/src/pages/test-env/JwtInspectPage.tsx +5 -3
  128. package/src/pages/test-env/RefreshTokenPage.tsx +157 -155
  129. package/src/pages/test-env/TestEnvPage.tsx +4 -2
  130. package/src/pages/verify-code/page.tsx +10 -6
  131. package/src/routes/auth/logout.ts +7 -25
  132. package/src/routes/auth/nextauth.ts +45 -71
  133. package/src/routes/auth/session.ts +25 -50
  134. package/src/routes/auth/viability.ts +7 -19
  135. package/src/server/auth.ts +60 -0
  136. package/src/stores/authStore.ts +1899 -1904
  137. package/src/utils/logout.ts +30 -30
  138. package/src/auth/auth-options.ts +0 -237
  139. package/src/auth/callbacks/index.ts +0 -7
  140. package/src/auth/callbacks/jwt.ts +0 -382
  141. package/src/auth/callbacks/session.ts +0 -243
  142. package/src/auth/callbacks/signin.ts +0 -56
  143. package/src/auth/events/index.ts +0 -5
  144. package/src/auth/events/signout.ts +0 -33
  145. package/src/auth/providers/credentials.ts +0 -256
  146. package/src/auth/providers/index.ts +0 -6
  147. package/src/auth/providers/oauth.ts +0 -114
  148. package/src/lib/nextauth-secret.ts +0 -121
  149. package/src/types/next-auth.d.ts +0 -15
@@ -13,9 +13,8 @@
13
13
  * @since auth-ready-v2
14
14
  */
15
15
  import { NextRequest, NextResponse } from 'next/server';
16
- import { JWT } from 'next-auth/jwt';
17
16
  export interface AuthContext {
18
- token: JWT;
17
+ token: any;
19
18
  accessToken: string;
20
19
  userId: string;
21
20
  sessionToken: string;
@@ -16,10 +16,9 @@
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.createAuthHandler = createAuthHandler;
18
18
  const server_1 = require("next/server");
19
- const jwt_1 = require("next-auth/jwt");
19
+ const auth_1 = require("../server/auth");
20
20
  const nanoid_1 = require("nanoid");
21
21
  const session_store_1 = require("../lib/session-store");
22
- const app_slug_1 = require("../lib/app-slug");
23
22
  /**
24
23
  * Creates an auth-aware handler with automatic token refresh
25
24
  *
@@ -262,14 +261,15 @@ function createAuthHandler(options = {}) {
262
261
  return {
263
262
  handle: (handler) => {
264
263
  return async (req, context = {}) => {
265
- // Extract token from NextAuth
266
- const token = await (0, jwt_1.getToken)({ req, secret: nextAuthSecret, cookieName: (0, app_slug_1.getJwtCookieName)() });
264
+ // Extract session from Better Auth
265
+ const betterAuthSession = await (0, auth_1.getSession)(req);
266
+ const token = betterAuthSession ? { ...betterAuthSession.user, ...betterAuthSession.session } : null;
267
267
  // Check if auth is required
268
- if (requireAuth && !token) {
268
+ if (requireAuth && !betterAuthSession) {
269
269
  return server_1.NextResponse.json({ error: 'Authentication required', code: 'UNAUTHORIZED' }, { status: 401 });
270
270
  }
271
- // If no token and auth not required, call handler without auth context
272
- if (!token) {
271
+ // If no session and auth not required, call handler without auth context
272
+ if (!betterAuthSession) {
273
273
  return handler(req, context, null);
274
274
  }
275
275
  // Validate client_slug (token confusion attack prevention)
@@ -305,8 +305,8 @@ function createAuthHandler(options = {}) {
305
305
  let authContext = {
306
306
  token,
307
307
  accessToken: token.accessToken || '',
308
- userId: token.sub || token.userId || '',
309
- sessionToken: token.redisSessionId || '',
308
+ userId: betterAuthSession.user?.id || token.userId || '',
309
+ sessionToken: betterAuthSession.session?.token || '',
310
310
  refreshToken: token.refreshToken,
311
311
  };
312
312
  // Check if token needs refresh
@@ -1,112 +1,110 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.POST = POST;
4
- const server_1 = require("next/server");
5
- const jwt_1 = require("next-auth/jwt");
6
- const session_store_1 = require("../../lib/session-store");
7
- const app_slug_1 = require("../../lib/app-slug");
8
- const nanoid_1 = require("nanoid");
9
- // ...
10
- async function POST(req) {
11
- const requestId = (0, nanoid_1.nanoid)();
12
- try {
13
- // Get session token from NextAuth JWT
14
- // Support both field names: sessionToken (auth.ts JWT) and redisSessionId (legacy)
15
- const token = await (0, jwt_1.getToken)({ req, secret: process.env.NEXTAUTH_SECRET, cookieName: (0, app_slug_1.getJwtCookieName)() });
16
- const sessionToken = (token?.sessionToken || token?.redisSessionId);
17
- if (!token || typeof sessionToken !== 'string') {
18
- return server_1.NextResponse.json({ success: false, message: 'Unauthorized' }, { status: 401 });
19
- }
20
- const sessionData = await (0, session_store_1.getSession)(sessionToken);
21
- // NOTE: Field is idpAccessToken (not accessToken) per normalized naming convention
22
- if (!sessionData?.idpAccessToken) {
23
- return server_1.NextResponse.json({
24
- success: false,
25
- message: 'Authentication required - no access token available',
26
- error_code: 'UNAUTHORIZED',
27
- request_id: requestId,
28
- }, { status: 401 });
29
- }
30
- const body = await req.json();
31
- const { current_password, new_password, confirm_password } = body;
32
- // Validate input
33
- if (!current_password || !new_password || !confirm_password) {
34
- return server_1.NextResponse.json({
35
- success: false,
36
- message: 'Current password, new password, and confirmation are required',
37
- error_code: 'VALIDATION_ERROR',
38
- request_id: requestId,
39
- }, { status: 400 });
40
- }
41
- if (new_password !== confirm_password) {
42
- return server_1.NextResponse.json({
43
- success: false,
44
- message: 'New password and confirmation do not match',
45
- error_code: 'VALIDATION_ERROR',
46
- request_id: requestId,
47
- }, { status: 400 });
48
- }
49
- // Get IDP base URL from environment
50
- const idpBaseUrl = process.env.IDP_URL;
51
- if (!idpBaseUrl) {
52
- console.error('[CHANGE_PASSWORD] IDP_URL not configured');
53
- return server_1.NextResponse.json({
54
- success: false,
55
- message: 'Service configuration error',
56
- error_code: 'CONFIGURATION_ERROR',
57
- request_id: requestId,
58
- }, { status: 500 });
59
- }
60
- // Proxy request to IDP
61
- const idpUrl = `${idpBaseUrl}/api/Account/change-password`;
62
- const idpResponse = await fetch(idpUrl, {
63
- method: 'POST',
64
- headers: {
65
- 'Content-Type': 'application/json',
66
- 'Authorization': `Bearer ${sessionData.idpAccessToken}`,
67
- 'x-request-id': requestId,
68
- },
69
- body: JSON.stringify({
70
- current_password,
71
- new_password,
72
- confirm_password,
73
- }),
74
- });
75
- const responseData = await idpResponse.json().catch(() => ({}));
76
- if (!idpResponse.ok) {
77
- // Extract error message from IDP response
78
- let errorMessage = 'Failed to change password';
79
- if (responseData.message) {
80
- errorMessage = responseData.message;
81
- }
82
- else if (responseData.details?.value && Array.isArray(responseData.details.value) && responseData.details.value.length > 0) {
83
- errorMessage = responseData.details.value[0].message || errorMessage;
84
- }
85
- else if (responseData.details?.message) {
86
- errorMessage = responseData.details.message;
87
- }
88
- return server_1.NextResponse.json({
89
- success: false,
90
- message: errorMessage,
91
- error_code: responseData.error_code || 'CHANGE_PASSWORD_FAILED',
92
- request_id: requestId,
93
- details: responseData.details,
94
- }, { status: idpResponse.status });
95
- }
96
- return server_1.NextResponse.json({
97
- success: true,
98
- message: responseData.message || 'Password changed successfully',
99
- request_id: requestId,
100
- });
101
- }
102
- catch (error) {
103
- console.error('[CHANGE_PASSWORD] Error:', error);
104
- const requestId = req.headers.get('x-request-id') ?? crypto.randomUUID();
105
- return server_1.NextResponse.json({
106
- success: false,
107
- message: error instanceof Error ? error.message : 'Failed to change password',
108
- error_code: 'INTERNAL_ERROR',
109
- request_id: requestId,
110
- }, { status: 500 });
111
- }
112
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = POST;
4
+ const server_1 = require("next/server");
5
+ const auth_1 = require("../../server/auth");
6
+ const session_store_1 = require("../../lib/session-store");
7
+ const nanoid_1 = require("nanoid");
8
+ // ...
9
+ async function POST(req) {
10
+ const requestId = (0, nanoid_1.nanoid)();
11
+ try {
12
+ // Get session from Better Auth
13
+ const betterAuthSession = await (0, auth_1.getSession)(req);
14
+ const sessionToken = betterAuthSession?.session?.token;
15
+ if (!betterAuthSession || typeof sessionToken !== 'string') {
16
+ return server_1.NextResponse.json({ success: false, message: 'Unauthorized' }, { status: 401 });
17
+ }
18
+ const sessionData = await (0, session_store_1.getSession)(sessionToken);
19
+ // NOTE: Field is idpAccessToken (not accessToken) per normalized naming convention
20
+ if (!sessionData?.idpAccessToken) {
21
+ return server_1.NextResponse.json({
22
+ success: false,
23
+ message: 'Authentication required - no access token available',
24
+ error_code: 'UNAUTHORIZED',
25
+ request_id: requestId,
26
+ }, { status: 401 });
27
+ }
28
+ const body = await req.json();
29
+ const { current_password, new_password, confirm_password } = body;
30
+ // Validate input
31
+ if (!current_password || !new_password || !confirm_password) {
32
+ return server_1.NextResponse.json({
33
+ success: false,
34
+ message: 'Current password, new password, and confirmation are required',
35
+ error_code: 'VALIDATION_ERROR',
36
+ request_id: requestId,
37
+ }, { status: 400 });
38
+ }
39
+ if (new_password !== confirm_password) {
40
+ return server_1.NextResponse.json({
41
+ success: false,
42
+ message: 'New password and confirmation do not match',
43
+ error_code: 'VALIDATION_ERROR',
44
+ request_id: requestId,
45
+ }, { status: 400 });
46
+ }
47
+ // Get IDP base URL from environment
48
+ const idpBaseUrl = process.env.IDP_URL;
49
+ if (!idpBaseUrl) {
50
+ console.error('[CHANGE_PASSWORD] IDP_URL not configured');
51
+ return server_1.NextResponse.json({
52
+ success: false,
53
+ message: 'Service configuration error',
54
+ error_code: 'CONFIGURATION_ERROR',
55
+ request_id: requestId,
56
+ }, { status: 500 });
57
+ }
58
+ // Proxy request to IDP
59
+ const idpUrl = `${idpBaseUrl}/api/Account/change-password`;
60
+ const idpResponse = await fetch(idpUrl, {
61
+ method: 'POST',
62
+ headers: {
63
+ 'Content-Type': 'application/json',
64
+ 'Authorization': `Bearer ${sessionData.idpAccessToken}`,
65
+ 'x-request-id': requestId,
66
+ },
67
+ body: JSON.stringify({
68
+ current_password,
69
+ new_password,
70
+ confirm_password,
71
+ }),
72
+ });
73
+ const responseData = await idpResponse.json().catch(() => ({}));
74
+ if (!idpResponse.ok) {
75
+ // Extract error message from IDP response
76
+ let errorMessage = 'Failed to change password';
77
+ if (responseData.message) {
78
+ errorMessage = responseData.message;
79
+ }
80
+ else if (responseData.details?.value && Array.isArray(responseData.details.value) && responseData.details.value.length > 0) {
81
+ errorMessage = responseData.details.value[0].message || errorMessage;
82
+ }
83
+ else if (responseData.details?.message) {
84
+ errorMessage = responseData.details.message;
85
+ }
86
+ return server_1.NextResponse.json({
87
+ success: false,
88
+ message: errorMessage,
89
+ error_code: responseData.error_code || 'CHANGE_PASSWORD_FAILED',
90
+ request_id: requestId,
91
+ details: responseData.details,
92
+ }, { status: idpResponse.status });
93
+ }
94
+ return server_1.NextResponse.json({
95
+ success: true,
96
+ message: responseData.message || 'Password changed successfully',
97
+ request_id: requestId,
98
+ });
99
+ }
100
+ catch (error) {
101
+ console.error('[CHANGE_PASSWORD] Error:', error);
102
+ const requestId = req.headers.get('x-request-id') ?? crypto.randomUUID();
103
+ return server_1.NextResponse.json({
104
+ success: false,
105
+ message: error instanceof Error ? error.message : 'Failed to change password',
106
+ error_code: 'INTERNAL_ERROR',
107
+ request_id: requestId,
108
+ }, { status: 500 });
109
+ }
110
+ }
@@ -1,20 +1,19 @@
1
- /**
2
- * Admin Analytics API Handler
3
- *
4
- * Provides admin-level analytics data using service account credentials.
5
- * Supports: geo stats, login stats, revenue stats, feature usage.
6
- *
7
- * @version 1.0
8
- * @requires Admin role (vibe_app_admin or payez_admin)
9
- */
10
- import { NextRequest, NextResponse } from 'next/server';
11
- export interface AdminAnalyticsHandlerConfig {
12
- getAuthOptions: () => Promise<any>;
13
- }
14
- /**
15
- * POST /api/admin/analytics
16
- * Body: { type: 'geo' | 'logins' | 'revenue' | 'features', period?: string }
17
- */
18
- export declare function createAnalyticsHandler(config: AdminAnalyticsHandlerConfig): {
19
- POST(request: NextRequest): Promise<NextResponse<unknown>>;
20
- };
1
+ /**
2
+ * Admin Analytics API Handler
3
+ *
4
+ * Provides admin-level analytics data using service account credentials.
5
+ * Supports: geo stats, login stats, revenue stats, feature usage.
6
+ *
7
+ * @version 1.0
8
+ * @requires Admin role (vibe_app_admin or payez_admin)
9
+ */
10
+ import { NextRequest, NextResponse } from 'next/server';
11
+ export interface AdminAnalyticsHandlerConfig {
12
+ }
13
+ /**
14
+ * POST /api/admin/analytics
15
+ * Body: { type: 'geo' | 'logins' | 'revenue' | 'features', period?: string }
16
+ */
17
+ export declare function createAnalyticsHandler(config: AdminAnalyticsHandlerConfig): {
18
+ POST(request: NextRequest): Promise<NextResponse<unknown>>;
19
+ };