@payez/next-mvp 3.9.1 → 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 (147) 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 -1020
  39. package/dist/client/fetch-with-auth.js +2 -2
  40. package/dist/components/SessionSync.js +121 -119
  41. package/dist/components/account/MobileNavDrawer.js +64 -64
  42. package/dist/components/account/UserAvatarMenu.js +91 -88
  43. package/dist/components/admin/VibeAdminLayout.js +71 -69
  44. package/dist/hooks/useAuth.js +9 -7
  45. package/dist/hooks/useAuthSettings.js +93 -93
  46. package/dist/hooks/useAvailableProviders.d.ts +43 -45
  47. package/dist/hooks/useAvailableProviders.js +112 -108
  48. package/dist/hooks/useSessionExpiration.d.ts +2 -3
  49. package/dist/hooks/useSessionExpiration.js +2 -2
  50. package/dist/hooks/useViabilitySession.js +3 -2
  51. package/dist/index.js +4 -6
  52. package/dist/lib/app-slug.d.ts +95 -95
  53. package/dist/lib/app-slug.js +172 -172
  54. package/dist/lib/standardized-client-api.js +10 -5
  55. package/dist/lib/startup-init.js +21 -25
  56. package/dist/lib/test-aware-get-token.js +86 -81
  57. package/dist/lib/token-lifecycle.d.ts +78 -52
  58. package/dist/lib/token-lifecycle.js +360 -398
  59. package/dist/pages/admin-login/page.js +73 -83
  60. package/dist/pages/client-admin/ClientSiteAdminPage.js +179 -177
  61. package/dist/pages/login/page.js +202 -211
  62. package/dist/pages/showcase/ShowcasePage.js +142 -140
  63. package/dist/pages/test-env/EmergencyLogoutPage.js +99 -98
  64. package/dist/pages/test-env/JwtInspectPage.js +116 -114
  65. package/dist/pages/test-env/RefreshTokenPage.js +4 -2
  66. package/dist/pages/test-env/TestEnvPage.js +51 -49
  67. package/dist/pages/verify-code/page.js +412 -408
  68. package/dist/routes/auth/logout.d.ts +31 -31
  69. package/dist/routes/auth/logout.js +98 -113
  70. package/dist/routes/auth/nextauth.d.ts +14 -11
  71. package/dist/routes/auth/nextauth.js +25 -57
  72. package/dist/routes/auth/session.js +157 -179
  73. package/dist/routes/auth/viability.js +190 -201
  74. package/dist/server/auth.d.ts +50 -0
  75. package/dist/server/auth.js +62 -0
  76. package/dist/stores/authStore.js +19 -23
  77. package/dist/utils/logout.js +5 -5
  78. package/package.json +1 -3
  79. package/src/api/auth-handler.ts +550 -549
  80. package/src/api-handlers/account/change-password.ts +5 -8
  81. package/src/api-handlers/admin/analytics.ts +4 -6
  82. package/src/api-handlers/admin/audit.ts +5 -7
  83. package/src/api-handlers/admin/index.ts +1 -2
  84. package/src/api-handlers/admin/redis-sessions.ts +6 -8
  85. package/src/api-handlers/admin/sessions.ts +5 -7
  86. package/src/api-handlers/admin/site-logs.ts +8 -10
  87. package/src/api-handlers/admin/stats.ts +4 -6
  88. package/src/api-handlers/admin/users.ts +5 -7
  89. package/src/api-handlers/admin/vibe-data.ts +10 -12
  90. package/src/api-handlers/auth/refresh.ts +5 -7
  91. package/src/api-handlers/auth/signout.ts +5 -6
  92. package/src/api-handlers/auth/status.ts +4 -7
  93. package/src/api-handlers/auth/update-session.ts +123 -125
  94. package/src/api-handlers/auth/verify-code.ts +9 -13
  95. package/src/api-handlers/session/viability.ts +10 -47
  96. package/src/api-handlers/test/force-expire.ts +4 -11
  97. package/src/auth/auth-decision.ts +1 -1
  98. package/src/auth/better-auth.ts +138 -141
  99. package/src/auth/route-config.ts +219 -219
  100. package/src/auth/utils/token-utils.ts +0 -1
  101. package/src/client/AuthContext.tsx +6 -2
  102. package/src/client/fetch-with-auth.ts +47 -47
  103. package/src/components/SessionSync.tsx +6 -5
  104. package/src/components/account/MobileNavDrawer.tsx +3 -3
  105. package/src/components/account/UserAvatarMenu.tsx +6 -3
  106. package/src/components/admin/VibeAdminLayout.tsx +4 -2
  107. package/src/config/logger.ts +1 -1
  108. package/src/hooks/useAuth.ts +117 -115
  109. package/src/hooks/useAuthSettings.ts +2 -2
  110. package/src/hooks/useAvailableProviders.ts +9 -5
  111. package/src/hooks/useSessionExpiration.ts +101 -102
  112. package/src/hooks/useViabilitySession.ts +336 -335
  113. package/src/index.ts +60 -63
  114. package/src/lib/api-handler.ts +0 -1
  115. package/src/lib/app-slug.ts +6 -6
  116. package/src/lib/standardized-client-api.ts +901 -895
  117. package/src/lib/startup-init.ts +243 -247
  118. package/src/lib/test-aware-get-token.ts +22 -12
  119. package/src/lib/token-lifecycle.ts +12 -53
  120. package/src/pages/admin-login/page.tsx +9 -17
  121. package/src/pages/client-admin/ClientSiteAdminPage.tsx +4 -2
  122. package/src/pages/login/page.tsx +21 -28
  123. package/src/pages/showcase/ShowcasePage.tsx +4 -2
  124. package/src/pages/test-env/EmergencyLogoutPage.tsx +7 -6
  125. package/src/pages/test-env/JwtInspectPage.tsx +5 -3
  126. package/src/pages/test-env/RefreshTokenPage.tsx +157 -155
  127. package/src/pages/test-env/TestEnvPage.tsx +4 -2
  128. package/src/pages/verify-code/page.tsx +10 -6
  129. package/src/routes/auth/logout.ts +7 -25
  130. package/src/routes/auth/nextauth.ts +45 -71
  131. package/src/routes/auth/session.ts +25 -50
  132. package/src/routes/auth/viability.ts +7 -19
  133. package/src/server/auth.ts +60 -0
  134. package/src/stores/authStore.ts +1899 -1904
  135. package/src/utils/logout.ts +30 -30
  136. package/src/auth/auth-options.ts +0 -237
  137. package/src/auth/callbacks/index.ts +0 -7
  138. package/src/auth/callbacks/jwt.ts +0 -382
  139. package/src/auth/callbacks/session.ts +0 -243
  140. package/src/auth/callbacks/signin.ts +0 -56
  141. package/src/auth/events/index.ts +0 -5
  142. package/src/auth/events/signout.ts +0 -33
  143. package/src/auth/providers/credentials.ts +0 -256
  144. package/src/auth/providers/index.ts +0 -6
  145. package/src/auth/providers/oauth.ts +0 -114
  146. package/src/lib/nextauth-secret.ts +0 -121
  147. 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
+ };