@payez/next-mvp 4.0.46 → 4.0.49

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 (63) hide show
  1. package/dist/api/auth-handler.d.ts +0 -2
  2. package/dist/api/auth-handler.js +1 -1
  3. package/dist/api-handlers/admin/stats.js +24 -14
  4. package/dist/api-handlers/auth/refresh.d.ts +4 -6
  5. package/dist/api-handlers/auth/refresh.js +5 -7
  6. package/dist/api-handlers/auth/signout.d.ts +6 -15
  7. package/dist/api-handlers/auth/signout.js +9 -16
  8. package/dist/api-handlers/auth/update-session.d.ts +6 -15
  9. package/dist/api-handlers/auth/update-session.js +7 -15
  10. package/dist/api-handlers/auth/verify-code.d.ts +6 -15
  11. package/dist/api-handlers/auth/verify-code.js +7 -15
  12. package/dist/api-handlers/session/viability.js +2 -2
  13. package/dist/auth/better-auth.d.ts +3 -19
  14. package/dist/auth/better-auth.js +7 -13
  15. package/dist/client/better-auth-client.d.ts +7 -8
  16. package/dist/client/better-auth-client.js +3 -4
  17. package/dist/lib/auth-secret.d.ts +17 -0
  18. package/dist/lib/{nextauth-secret.js → auth-secret.js} +31 -15
  19. package/dist/lib/demo-mode.js +3 -1
  20. package/dist/lib/idp-client-config.d.ts +6 -2
  21. package/dist/lib/idp-client-config.js +35 -21
  22. package/dist/lib/secret-validation.d.ts +1 -1
  23. package/dist/lib/secret-validation.js +2 -2
  24. package/dist/lib/startup-init.d.ts +3 -3
  25. package/dist/lib/startup-init.js +23 -18
  26. package/dist/lib/test-aware-get-token.js +2 -51
  27. package/dist/routes/account/masked-info.d.ts +1 -1
  28. package/dist/routes/account/masked-info.js +1 -1
  29. package/dist/routes/account/send-code.d.ts +1 -1
  30. package/dist/routes/account/send-code.js +1 -1
  31. package/dist/routes/account/verify-email.d.ts +1 -1
  32. package/dist/routes/account/verify-email.js +1 -1
  33. package/dist/routes/account/verify-sms.d.ts +1 -1
  34. package/dist/routes/account/verify-sms.js +1 -1
  35. package/dist/routes/auth/refresh.js +3 -8
  36. package/dist/server/auth.d.ts +28 -7
  37. package/dist/server/auth.js +106 -55
  38. package/dist/server/decode-session.js +2 -2
  39. package/dist/vibe/hooks/index.d.ts +1 -1
  40. package/package.json +888 -893
  41. package/src/api/auth-handler.ts +0 -4
  42. package/src/api-handlers/admin/stats.ts +249 -238
  43. package/src/api-handlers/auth/refresh.ts +5 -8
  44. package/src/api-handlers/auth/signout.ts +9 -21
  45. package/src/api-handlers/auth/update-session.ts +7 -20
  46. package/src/api-handlers/auth/verify-code.ts +7 -20
  47. package/src/api-handlers/session/viability.ts +2 -2
  48. package/src/auth/better-auth.ts +7 -32
  49. package/src/client/better-auth-client.ts +3 -4
  50. package/src/lib/{nextauth-secret.ts → auth-secret.ts} +32 -16
  51. package/src/lib/demo-mode.ts +5 -1
  52. package/src/lib/idp-client-config.ts +42 -22
  53. package/src/lib/secret-validation.ts +1 -1
  54. package/src/lib/startup-init.ts +23 -18
  55. package/src/lib/test-aware-get-token.ts +2 -51
  56. package/src/routes/account/masked-info.ts +1 -1
  57. package/src/routes/account/send-code.ts +1 -1
  58. package/src/routes/account/verify-email.ts +1 -1
  59. package/src/routes/account/verify-sms.ts +1 -1
  60. package/src/routes/auth/refresh.ts +3 -8
  61. package/src/server/auth.ts +129 -22
  62. package/src/server/decode-session.ts +2 -2
  63. package/dist/lib/nextauth-secret.d.ts +0 -10
@@ -1,55 +1,71 @@
1
1
  "use strict";
2
2
  /**
3
- * Server-side auth utilities for Better Auth (v4.0)
3
+ * Server-side auth utilities for Better Auth.
4
4
  *
5
- * Replaces:
6
- * - getToken() from next-auth/jwt
7
- * - getServerSession() from next-auth
8
- *
9
- * All server-side auth flows go through the Better Auth instance.
5
+ * All server-side auth flows go through the Better Auth instance returned by
6
+ * getAuthInstance(); use getSession(req) for the request-scoped session.
10
7
  */
11
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
- if (k2 === undefined) k2 = k;
13
- var desc = Object.getOwnPropertyDescriptor(m, k);
14
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
- desc = { enumerable: true, get: function() { return m[k]; } };
16
- }
17
- Object.defineProperty(o, k2, desc);
18
- }) : (function(o, m, k, k2) {
19
- if (k2 === undefined) k2 = k;
20
- o[k2] = m[k];
21
- }));
22
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
- Object.defineProperty(o, "default", { enumerable: true, value: v });
24
- }) : function(o, v) {
25
- o["default"] = v;
26
- });
27
- var __importStar = (this && this.__importStar) || (function () {
28
- var ownKeys = function(o) {
29
- ownKeys = Object.getOwnPropertyNames || function (o) {
30
- var ar = [];
31
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
- return ar;
33
- };
34
- return ownKeys(o);
35
- };
36
- return function (mod) {
37
- if (mod && mod.__esModule) return mod;
38
- var result = {};
39
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
- __setModuleDefault(result, mod);
41
- return result;
42
- };
43
- })();
44
8
  Object.defineProperty(exports, "__esModule", { value: true });
45
9
  exports.getAuthInstance = getAuthInstance;
46
10
  exports.getSession = getSession;
11
+ exports.getSessionData = getSessionData;
12
+ exports.getIdpToken = getIdpToken;
47
13
  exports.requireSession = requireSession;
48
14
  require("server-only");
49
15
  const better_auth_1 = require("../auth/better-auth");
50
16
  const idp_client_config_1 = require("../lib/idp-client-config");
17
+ const session_store_1 = require("../lib/session-store");
51
18
  let authInstance = null;
52
19
  let authInitPromise = null;
20
+ function buildSessionDataFromAuthSession(session) {
21
+ const user = session?.user;
22
+ if (!user?.id && !user?.email) {
23
+ return null;
24
+ }
25
+ const expiresAt = session?.session?.expiresAt
26
+ ? new Date(session.session.expiresAt).getTime()
27
+ : Date.now() + 24 * 60 * 60 * 1000;
28
+ return {
29
+ userId: user.userId || user.id || '',
30
+ email: user.email || '',
31
+ name: user.name || undefined,
32
+ roles: Array.isArray(user.roles) ? user.roles : [],
33
+ idpAccessToken: user.idpAccessToken,
34
+ idpRefreshToken: user.idpRefreshToken,
35
+ idpAccessTokenExpires: user.idpAccessTokenExpires || expiresAt,
36
+ mfaVerified: user.mfaVerified ?? user.twoFactorSessionVerified ?? false,
37
+ oauthProvider: user.oauthProvider,
38
+ idpClientId: user.idpClientId,
39
+ merchantId: user.merchantId,
40
+ };
41
+ }
42
+ function attachSessionData(session, sessionData, sessionToken) {
43
+ if (!sessionData) {
44
+ return session;
45
+ }
46
+ const enrichedSessionData = {
47
+ ...sessionData,
48
+ ...(sessionToken ? { sessionToken } : {}),
49
+ };
50
+ session.sessionData = enrichedSessionData;
51
+ if (session?.user) {
52
+ const user = session.user;
53
+ user.userId = enrichedSessionData.userId || user.userId;
54
+ user.email = enrichedSessionData.email || user.email;
55
+ user.name = enrichedSessionData.name || user.name;
56
+ user.roles = enrichedSessionData.roles || user.roles || [];
57
+ user.idpAccessToken = enrichedSessionData.idpAccessToken;
58
+ user.idpRefreshToken = enrichedSessionData.idpRefreshToken;
59
+ user.idpAccessTokenExpires = enrichedSessionData.idpAccessTokenExpires;
60
+ user.mfaVerified = enrichedSessionData.mfaVerified;
61
+ user.twoFactorSessionVerified =
62
+ enrichedSessionData.mfaVerified ?? user.twoFactorSessionVerified;
63
+ user.oauthProvider = enrichedSessionData.oauthProvider || user.oauthProvider;
64
+ user.idpClientId = enrichedSessionData.idpClientId || user.idpClientId;
65
+ user.merchantId = enrichedSessionData.merchantId || user.merchantId;
66
+ }
67
+ return session;
68
+ }
53
69
  /**
54
70
  * Get the initialized Better Auth instance (singleton).
55
71
  */
@@ -78,31 +94,66 @@ async function getSession(request) {
78
94
  const session = await auth.api.getSession({ headers: request.headers });
79
95
  if (!session?.session?.token || !session?.user)
80
96
  return session;
81
- // Enrich with IDP tokens from Redis (stored by post-login hook)
97
+ const sessionToken = session.session.token;
98
+ let sessionData = null;
99
+ // Prefer the app's normalized Redis session. Fall back to Better Auth's
100
+ // secondary storage record, then finally to whatever Better Auth already
101
+ // put on the request session object.
82
102
  try {
83
- const { getRedis } = await Promise.resolve().then(() => __importStar(require('../lib/redis')));
84
- const { getAppSlug } = await Promise.resolve().then(() => __importStar(require('../lib/app-slug')));
85
- const baKey = `ba:${getAppSlug()}:${session.session.token}`;
86
- const baRaw = await getRedis().get(baKey);
87
- if (baRaw) {
88
- const baData = JSON.parse(baRaw);
89
- if (baData.idpTokens) {
90
- const u = session.user;
91
- u.roles = baData.idpTokens.roles || [];
92
- u.userId = baData.idpTokens.userId;
93
- u.idpAccessToken = baData.idpTokens.idpAccessToken;
94
- u.idpRefreshToken = baData.idpTokens.idpRefreshToken;
95
- u.idpAccessTokenExpires = baData.idpTokens.idpAccessTokenExpires;
96
- }
103
+ sessionData = await (0, session_store_1.getSession)(sessionToken);
104
+ if (!sessionData) {
105
+ sessionData = await (0, session_store_1.getBetterAuthSession)(sessionToken);
97
106
  }
98
107
  }
99
108
  catch { /* Redis unavailable */ }
100
- return session;
109
+ if (!sessionData) {
110
+ sessionData = buildSessionDataFromAuthSession(session);
111
+ }
112
+ return attachSessionData(session, sessionData, sessionToken);
101
113
  }
102
114
  catch {
103
115
  return null;
104
116
  }
105
117
  }
118
+ /**
119
+ * Get normalized session data for the current request.
120
+ *
121
+ * This prefers the app's Redis session because it carries the canonical
122
+ * IDP token, roles, and tenant-specific user identity used by app routes.
123
+ */
124
+ async function getSessionData(request) {
125
+ const session = await getSession(request);
126
+ const sessionData = session?.sessionData ||
127
+ buildSessionDataFromAuthSession(session);
128
+ if (!sessionData) {
129
+ return null;
130
+ }
131
+ const sessionToken = session?.session?.token;
132
+ return sessionToken
133
+ ? { ...sessionData, sessionToken }
134
+ : sessionData;
135
+ }
136
+ /**
137
+ * Get the current request's IDP access token without triggering a refresh.
138
+ *
139
+ * Use this for routes that only need the currently-issued bearer token and
140
+ * should fail closed instead of performing token lifecycle work.
141
+ */
142
+ async function getIdpToken(request) {
143
+ const sessionData = await getSessionData(request);
144
+ if (!sessionData) {
145
+ return { success: false, error: 'NO_SESSION', terminal: true };
146
+ }
147
+ const accessToken = sessionData.idpAccessToken || sessionData.accessToken;
148
+ if (!accessToken) {
149
+ return { success: false, error: 'NO_TOKEN', terminal: true };
150
+ }
151
+ return {
152
+ success: true,
153
+ accessToken,
154
+ sessionData,
155
+ };
156
+ }
106
157
  /**
107
158
  * Get the current session, throwing if not authenticated.
108
159
  * Use in API handlers that require auth.
@@ -166,9 +166,9 @@ async function decodeSession(requestCookies) {
166
166
  return null;
167
167
  }
168
168
  const config = await (0, idp_client_config_1.getIDPClientConfig)();
169
- const secret = config.nextAuthSecret;
169
+ const secret = config.authSecret;
170
170
  if (!secret) {
171
- console.error('[DECODE-SESSION] No nextAuthSecret available from IDP config');
171
+ console.error('[DECODE-SESSION] No authSecret available from IDP config');
172
172
  return null;
173
173
  }
174
174
  const secretKey = new TextEncoder().encode(secret);
@@ -141,7 +141,7 @@ export declare function useVibeMutation<T extends VibeTableName, Op extends Muta
141
141
  /**
142
142
  * Convenience hook for creating records.
143
143
  */
144
- export declare function useVibeCreate<T extends VibeTableName>(table: T, options?: Omit<UseVibeMutationOptions<T, 'create'>, never>): import("@tanstack/react-query").UseMutationResult<VibeTableType<T>, VibeError, Omit<VibeTableType<T>, "id" | "created_at" | "updated_at">, unknown>;
144
+ export declare function useVibeCreate<T extends VibeTableName>(table: T, options?: Omit<UseVibeMutationOptions<T, 'create'>, never>): import("@tanstack/react-query").UseMutationResult<VibeTableType<T>, VibeError, Omit<VibeTableType<T>, "created_at" | "id" | "updated_at">, unknown>;
145
145
  /**
146
146
  * Convenience hook for updating records.
147
147
  */