@neondatabase/auth 0.3.0-beta → 0.4.1-beta

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 (33) hide show
  1. package/README.md +22 -7
  2. package/codemods/migrate-auth-ui-imports.mjs +439 -0
  3. package/dist/{adapter-core-D00qcqMo.mjs → adapter-core-BFMM3lwe.mjs} +21 -11
  4. package/dist/{adapter-core-B9uDhoYq.d.mts → adapter-core-ClY-p_AI.d.mts} +325 -190
  5. package/dist/auth-interface-Clz-oWq1.d.mts +8 -0
  6. package/dist/better-auth-helpers-Bkezghej.mjs +541 -0
  7. package/dist/{better-auth-react-adapter-Xdj-69i9.mjs → better-auth-react-adapter-DZTZVVnk.mjs} +1 -1
  8. package/dist/{better-auth-react-adapter-BO4jLN4H.d.mts → better-auth-react-adapter-iJMZCLUI.d.mts} +388 -301
  9. package/dist/index.d.mts +5 -4
  10. package/dist/index.mjs +4 -3
  11. package/dist/{neon-auth-DBOB8sXF.mjs → neon-auth-VDrC3GwX.mjs} +1 -1
  12. package/dist/next/index.d.mts +144 -56
  13. package/dist/next/index.mjs +5 -4
  14. package/dist/next/server/index.d.mts +131 -14
  15. package/dist/next/server/index.mjs +402 -52
  16. package/dist/react/adapters/index.d.mts +3 -3
  17. package/dist/react/adapters/index.mjs +2 -2
  18. package/dist/react/index.d.mts +4 -4
  19. package/dist/react/index.mjs +2 -2
  20. package/dist/react/ui/index.d.mts +1 -1
  21. package/dist/{supabase-adapter-CIBMebXB.mjs → supabase-adapter-CAyBFrNn.mjs} +3 -514
  22. package/dist/{supabase-adapter-CSDRL1ZU.d.mts → supabase-adapter-cuLnmLDs.d.mts} +390 -303
  23. package/dist/types/index.d.mts +2 -2
  24. package/dist/vanilla/adapters/index.d.mts +4 -3
  25. package/dist/vanilla/adapters/index.mjs +2 -2
  26. package/dist/vanilla/index.d.mts +4 -3
  27. package/dist/vanilla/index.mjs +2 -2
  28. package/llms.txt +2 -2
  29. package/package.json +6 -2
  30. package/dist/constants-Cupc_bln.mjs +0 -28
  31. /package/dist/{index-CPnFzULh.d.mts → index-B0Pd4HOH.d.mts} +0 -0
  32. /package/dist/{index-UW23fDSn.d.mts → index-CzpoWrv9.d.mts} +0 -0
  33. /package/dist/{index-B_Q0Tp1D.d.mts → index-DHryUj7e.d.mts} +0 -0
@@ -0,0 +1,8 @@
1
+ import { AuthApiError, AuthClient, AuthError, isAuthApiError, isAuthError } from "@supabase/auth-js";
2
+
3
+ //#region src/adapters/supabase/auth-interface.d.ts
4
+ type _UpstreamAuthClientInstance = InstanceType<typeof AuthClient>;
5
+ type _AuthClientBase = { [K in keyof _UpstreamAuthClientInstance as _UpstreamAuthClientInstance[K] extends never ? never : K]: _UpstreamAuthClientInstance[K] };
6
+ type SupabaseAuthClientInterface = _AuthClientBase;
7
+ //#endregion
8
+ export { isAuthError as a, isAuthApiError as i, AuthError as n, SupabaseAuthClientInterface as r, AuthApiError as t };
@@ -0,0 +1,541 @@
1
+ import { AuthApiError, AuthError, isAuthApiError, isAuthError } from "@supabase/auth-js";
2
+
3
+ //#region src/core/constants.ts
4
+ /**
5
+ * Session caching configuration constants
6
+ *
7
+ * Uses industry-standard 60s cache TTL (common across auth providers).
8
+ *
9
+ * Note: Token refresh detection is now automatic via Better Auth's
10
+ * fetchOptions.onSuccess callback. No polling is needed.
11
+ */
12
+ /** Session cache TTL in milliseconds (60 seconds) */
13
+ const SESSION_CACHE_TTL_MS = 6e4;
14
+ /** Clock skew buffer for token expiration checks in milliseconds (10 seconds) */
15
+ const CLOCK_SKEW_BUFFER_MS = 1e4;
16
+ /** Default session expiry duration in milliseconds (1 hour) */
17
+ const DEFAULT_SESSION_EXPIRY_MS = 36e5;
18
+ /** Name of the session verifier parameter in the URL, used for the OAUTH flow */
19
+ const NEON_AUTH_SESSION_VERIFIER_PARAM_NAME = "neon_auth_session_verifier";
20
+ /** Name of the popup marker parameter in the URL, used for OAuth popup flow in iframes */
21
+ const NEON_AUTH_POPUP_PARAM_NAME = "neon_popup";
22
+ /** Name of the original callback URL parameter, used in OAuth popup flow */
23
+ const NEON_AUTH_POPUP_CALLBACK_PARAM_NAME = "neon_popup_callback";
24
+ /** The callback route used for OAuth popup completion (must be in middleware SKIP_ROUTES) */
25
+ const NEON_AUTH_POPUP_CALLBACK_ROUTE = "/auth/callback";
26
+ /** Message type for OAuth popup completion postMessage */
27
+ const OAUTH_POPUP_MESSAGE_TYPE = "neon-auth:oauth-complete";
28
+
29
+ //#endregion
30
+ //#region src/utils/date.ts
31
+ function toISOString(date) {
32
+ if (!date) return (/* @__PURE__ */ new Date()).toISOString();
33
+ if (typeof date === "string") return date;
34
+ if (typeof date === "number") return new Date(date).toISOString();
35
+ return date.toISOString();
36
+ }
37
+
38
+ //#endregion
39
+ //#region src/adapters/supabase/errors/definitions.ts
40
+ /**
41
+ * Error codes for type-safe error handling
42
+ */
43
+ const AuthErrorCode = {
44
+ BadJwt: "bad_jwt",
45
+ InvalidCredentials: "invalid_credentials",
46
+ SessionExpired: "session_expired",
47
+ SessionNotFound: "session_not_found",
48
+ InvalidGrant: "invalid_grant",
49
+ UserNotFound: "user_not_found",
50
+ UserAlreadyExists: "user_already_exists",
51
+ EmailExists: "email_exists",
52
+ PhoneExists: "phone_exists",
53
+ EmailNotConfirmed: "email_not_confirmed",
54
+ PhoneNotConfirmed: "phone_not_confirmed",
55
+ ValidationFailed: "validation_failed",
56
+ BadJson: "bad_json",
57
+ WeakPassword: "weak_password",
58
+ EmailAddressInvalid: "email_address_invalid",
59
+ FeatureNotSupported: "feature_not_supported",
60
+ NotImplemented: "not_implemented",
61
+ OAuthProviderNotSupported: "oauth_provider_not_supported",
62
+ PhoneProviderDisabled: "phone_provider_disabled",
63
+ MagicLinkNotSupported: "magic_link_not_supported",
64
+ SsoProviderDisabled: "sso_provider_disabled",
65
+ AnonymousProviderDisabled: "anonymous_provider_disabled",
66
+ Web3ProviderDisabled: "web3_provider_disabled",
67
+ BadOAuthCallback: "bad_oauth_callback",
68
+ OAuthCallbackFailed: "oauth_callback_failed",
69
+ OverRequestRateLimit: "over_request_rate_limit",
70
+ OverEmailSendRateLimit: "over_email_send_rate_limit",
71
+ OverSmsSendRateLimit: "over_sms_send_rate_limit",
72
+ UnexpectedFailure: "unexpected_failure",
73
+ InternalError: "internal_error",
74
+ IdentityNotFound: "identity_not_found",
75
+ UnknownError: "unknown_error"
76
+ };
77
+ /**
78
+ * Complete error definitions map
79
+ * Maps error codes to HTTP status codes and default messages
80
+ */
81
+ const ERROR_DEFINITIONS = {
82
+ [AuthErrorCode.BadJwt]: {
83
+ code: AuthErrorCode.BadJwt,
84
+ status: 401,
85
+ message: "Invalid or expired session token",
86
+ description: "The JWT token is malformed, expired, or has an invalid signature"
87
+ },
88
+ [AuthErrorCode.InvalidCredentials]: {
89
+ code: AuthErrorCode.InvalidCredentials,
90
+ status: 401,
91
+ message: "Invalid email or password",
92
+ description: "The provided credentials do not match any user account"
93
+ },
94
+ [AuthErrorCode.SessionExpired]: {
95
+ code: AuthErrorCode.SessionExpired,
96
+ status: 401,
97
+ message: "Session has expired",
98
+ description: "The user session has exceeded its timeout period"
99
+ },
100
+ [AuthErrorCode.SessionNotFound]: {
101
+ code: AuthErrorCode.SessionNotFound,
102
+ status: 401,
103
+ message: "No active session found",
104
+ description: "The user does not have an active session or the session was invalidated"
105
+ },
106
+ [AuthErrorCode.InvalidGrant]: {
107
+ code: AuthErrorCode.InvalidGrant,
108
+ status: 401,
109
+ message: "Invalid authorization grant",
110
+ description: "OAuth/OIDC grant validation failed"
111
+ },
112
+ [AuthErrorCode.UserNotFound]: {
113
+ code: AuthErrorCode.UserNotFound,
114
+ status: 404,
115
+ message: "User not found",
116
+ description: "No user exists with the provided identifier"
117
+ },
118
+ [AuthErrorCode.UserAlreadyExists]: {
119
+ code: AuthErrorCode.UserAlreadyExists,
120
+ status: 409,
121
+ message: "User already exists",
122
+ description: "A user with this email or phone number is already registered"
123
+ },
124
+ [AuthErrorCode.EmailExists]: {
125
+ code: AuthErrorCode.EmailExists,
126
+ status: 409,
127
+ message: "Email address already registered",
128
+ description: "This email address is already associated with an account"
129
+ },
130
+ [AuthErrorCode.PhoneExists]: {
131
+ code: AuthErrorCode.PhoneExists,
132
+ status: 409,
133
+ message: "Phone number already registered",
134
+ description: "This phone number is already associated with an account"
135
+ },
136
+ [AuthErrorCode.EmailNotConfirmed]: {
137
+ code: AuthErrorCode.EmailNotConfirmed,
138
+ status: 422,
139
+ message: "Email verification required",
140
+ description: "The user must verify their email before signing in"
141
+ },
142
+ [AuthErrorCode.PhoneNotConfirmed]: {
143
+ code: AuthErrorCode.PhoneNotConfirmed,
144
+ status: 422,
145
+ message: "Phone verification required",
146
+ description: "The user must verify their phone number before signing in"
147
+ },
148
+ [AuthErrorCode.ValidationFailed]: {
149
+ code: AuthErrorCode.ValidationFailed,
150
+ status: 400,
151
+ message: "Invalid request parameters",
152
+ description: "One or more request parameters are invalid or missing"
153
+ },
154
+ [AuthErrorCode.BadJson]: {
155
+ code: AuthErrorCode.BadJson,
156
+ status: 400,
157
+ message: "Invalid JSON in request body",
158
+ description: "The request body contains malformed JSON"
159
+ },
160
+ [AuthErrorCode.WeakPassword]: {
161
+ code: AuthErrorCode.WeakPassword,
162
+ status: 400,
163
+ message: "Password does not meet security requirements",
164
+ description: "The password is too weak or does not meet complexity requirements"
165
+ },
166
+ [AuthErrorCode.EmailAddressInvalid]: {
167
+ code: AuthErrorCode.EmailAddressInvalid,
168
+ status: 400,
169
+ message: "Invalid email address format",
170
+ description: "The provided email address is not in a valid format"
171
+ },
172
+ [AuthErrorCode.FeatureNotSupported]: {
173
+ code: AuthErrorCode.FeatureNotSupported,
174
+ status: 403,
175
+ message: "Feature not available",
176
+ description: "This feature is not supported in the current configuration"
177
+ },
178
+ [AuthErrorCode.NotImplemented]: {
179
+ code: AuthErrorCode.NotImplemented,
180
+ status: 501,
181
+ message: "Feature not implemented",
182
+ description: "This feature has not been implemented yet"
183
+ },
184
+ [AuthErrorCode.OAuthProviderNotSupported]: {
185
+ code: AuthErrorCode.OAuthProviderNotSupported,
186
+ status: 403,
187
+ message: "OAuth provider not supported",
188
+ description: "The requested OAuth provider is not enabled"
189
+ },
190
+ [AuthErrorCode.PhoneProviderDisabled]: {
191
+ code: AuthErrorCode.PhoneProviderDisabled,
192
+ status: 403,
193
+ message: "Phone authentication not available",
194
+ description: "Phone number authentication is not enabled"
195
+ },
196
+ [AuthErrorCode.MagicLinkNotSupported]: {
197
+ code: AuthErrorCode.MagicLinkNotSupported,
198
+ status: 403,
199
+ message: "Magic link authentication not available",
200
+ description: "Magic link authentication is not supported"
201
+ },
202
+ [AuthErrorCode.SsoProviderDisabled]: {
203
+ code: AuthErrorCode.SsoProviderDisabled,
204
+ status: 403,
205
+ message: "SSO not supported",
206
+ description: "Enterprise SSO authentication is not available"
207
+ },
208
+ [AuthErrorCode.AnonymousProviderDisabled]: {
209
+ code: AuthErrorCode.AnonymousProviderDisabled,
210
+ status: 403,
211
+ message: "Anonymous authentication not available",
212
+ description: "Anonymous sign-in is not enabled"
213
+ },
214
+ [AuthErrorCode.Web3ProviderDisabled]: {
215
+ code: AuthErrorCode.Web3ProviderDisabled,
216
+ status: 403,
217
+ message: "Web3 authentication not supported",
218
+ description: "Web3/blockchain authentication is not available"
219
+ },
220
+ [AuthErrorCode.BadOAuthCallback]: {
221
+ code: AuthErrorCode.BadOAuthCallback,
222
+ status: 400,
223
+ message: "Invalid OAuth callback",
224
+ description: "The OAuth callback request is missing required parameters"
225
+ },
226
+ [AuthErrorCode.OAuthCallbackFailed]: {
227
+ code: AuthErrorCode.OAuthCallbackFailed,
228
+ status: 500,
229
+ message: "OAuth authentication failed",
230
+ description: "The OAuth callback completed but no session was created"
231
+ },
232
+ [AuthErrorCode.OverRequestRateLimit]: {
233
+ code: AuthErrorCode.OverRequestRateLimit,
234
+ status: 429,
235
+ message: "Too many requests",
236
+ description: "Rate limit exceeded. Please try again later"
237
+ },
238
+ [AuthErrorCode.OverEmailSendRateLimit]: {
239
+ code: AuthErrorCode.OverEmailSendRateLimit,
240
+ status: 429,
241
+ message: "Too many email requests",
242
+ description: "Too many emails sent. Please wait before trying again"
243
+ },
244
+ [AuthErrorCode.OverSmsSendRateLimit]: {
245
+ code: AuthErrorCode.OverSmsSendRateLimit,
246
+ status: 429,
247
+ message: "Too many SMS requests",
248
+ description: "Too many SMS messages sent. Please wait before trying again"
249
+ },
250
+ [AuthErrorCode.UnexpectedFailure]: {
251
+ code: AuthErrorCode.UnexpectedFailure,
252
+ status: 500,
253
+ message: "An unexpected error occurred",
254
+ description: "The server encountered an unexpected condition"
255
+ },
256
+ [AuthErrorCode.InternalError]: {
257
+ code: AuthErrorCode.InternalError,
258
+ status: 500,
259
+ message: "Internal server error",
260
+ description: "An internal error occurred while processing the request"
261
+ },
262
+ [AuthErrorCode.IdentityNotFound]: {
263
+ code: AuthErrorCode.IdentityNotFound,
264
+ status: 404,
265
+ message: "Identity not found",
266
+ description: "The requested user identity does not exist"
267
+ },
268
+ [AuthErrorCode.UnknownError]: {
269
+ code: AuthErrorCode.UnknownError,
270
+ status: 500,
271
+ message: "An unknown error occurred",
272
+ description: "The error could not be categorized"
273
+ }
274
+ };
275
+ /**
276
+ * Helper to get error definition by code
277
+ */
278
+ function getErrorDefinition(code) {
279
+ return ERROR_DEFINITIONS[code];
280
+ }
281
+ /**
282
+ * Create an AuthError or AuthApiError with proper status and message
283
+ *
284
+ * @param code - The error code from AuthErrorCode
285
+ * @param customMessage - Optional custom message (defaults to error definition message)
286
+ * @returns AuthError for 5xx errors, AuthApiError for 4xx errors
287
+ */
288
+ function createAuthError(code, customMessage) {
289
+ const def = getErrorDefinition(code);
290
+ const message = customMessage || def.message;
291
+ const status = def.status;
292
+ if (status !== 500 && status !== 501 && status !== 503) return new AuthApiError(message, status, def.code);
293
+ return new AuthError(message, status, def.code);
294
+ }
295
+
296
+ //#endregion
297
+ //#region src/adapters/supabase/errors/mappings.ts
298
+ /**
299
+ * Maps Better Auth error codes to AuthErrorCode
300
+ * Based on Better Auth SDK error codes
301
+ *
302
+ * @see https://www.better-auth.com/docs/concepts/error-handling
303
+ */
304
+ const BETTER_AUTH_ERROR_MAP = {
305
+ "INVALID_EMAIL_OR_PASSWORD": AuthErrorCode.InvalidCredentials,
306
+ "INVALID_PASSWORD": AuthErrorCode.InvalidCredentials,
307
+ "INVALID_EMAIL": AuthErrorCode.EmailAddressInvalid,
308
+ "USER_NOT_FOUND": AuthErrorCode.UserNotFound,
309
+ "INVALID_TOKEN": AuthErrorCode.BadJwt,
310
+ "SESSION_EXPIRED": AuthErrorCode.SessionExpired,
311
+ "FAILED_TO_GET_SESSION": AuthErrorCode.SessionNotFound,
312
+ "USER_ALREADY_EXISTS": AuthErrorCode.UserAlreadyExists,
313
+ "EMAIL_NOT_VERIFIED": AuthErrorCode.EmailNotConfirmed,
314
+ "USER_EMAIL_NOT_FOUND": AuthErrorCode.UserNotFound,
315
+ "PASSWORD_TOO_SHORT": AuthErrorCode.WeakPassword,
316
+ "PASSWORD_TOO_LONG": AuthErrorCode.WeakPassword,
317
+ "USER_ALREADY_HAS_PASSWORD": AuthErrorCode.ValidationFailed,
318
+ "CREDENTIAL_ACCOUNT_NOT_FOUND": AuthErrorCode.IdentityNotFound,
319
+ "FAILED_TO_UNLINK_LAST_ACCOUNT": AuthErrorCode.ValidationFailed,
320
+ "ACCOUNT_NOT_FOUND": AuthErrorCode.IdentityNotFound,
321
+ "SOCIAL_ACCOUNT_ALREADY_LINKED": AuthErrorCode.ValidationFailed,
322
+ "PROVIDER_NOT_FOUND": AuthErrorCode.OAuthProviderNotSupported,
323
+ "ID_TOKEN_NOT_SUPPORTED": AuthErrorCode.FeatureNotSupported,
324
+ "FAILED_TO_CREATE_USER": AuthErrorCode.InternalError,
325
+ "FAILED_TO_CREATE_SESSION": AuthErrorCode.InternalError,
326
+ "FAILED_TO_UPDATE_USER": AuthErrorCode.InternalError,
327
+ "EMAIL_CAN_NOT_BE_UPDATED": AuthErrorCode.FeatureNotSupported
328
+ };
329
+ /**
330
+ * Maps HTTP status codes from Better Auth to AuthErrorCode
331
+ */
332
+ const STATUS_CODE_ERROR_MAP = {
333
+ 400: AuthErrorCode.ValidationFailed,
334
+ 401: AuthErrorCode.BadJwt,
335
+ 403: AuthErrorCode.FeatureNotSupported,
336
+ 404: AuthErrorCode.UserNotFound,
337
+ 409: AuthErrorCode.UserAlreadyExists,
338
+ 422: AuthErrorCode.ValidationFailed,
339
+ 429: AuthErrorCode.OverRequestRateLimit,
340
+ 500: AuthErrorCode.UnexpectedFailure,
341
+ 501: AuthErrorCode.NotImplemented,
342
+ 503: AuthErrorCode.FeatureNotSupported
343
+ };
344
+
345
+ //#endregion
346
+ //#region src/core/better-auth-helpers.ts
347
+ /**
348
+ * Normalize Better Auth errors to standard AuthError format
349
+ *
350
+ * Handles three error formats:
351
+ * 1. BetterFetchError: { status, statusText, message?, code? }
352
+ * 2. BetterAuthErrorResponse: { status, statusText, message?, code? }
353
+ * 3. Standard Error: { message, name, stack }
354
+ *
355
+ * Maps Better Auth errors to appropriate AuthError/AuthApiError with:
356
+ * - Correct HTTP status codes
357
+ * - Standard error codes (snake_case)
358
+ * - User-friendly, security-conscious messages
359
+ */
360
+ function normalizeBetterAuthError(error) {
361
+ if (error !== null && error !== void 0 && typeof error === "object" && "status" in error && "statusText" in error) {
362
+ const betterError = error;
363
+ const status = betterError.status;
364
+ if ("code" in betterError && betterError.code && typeof betterError.code === "string") {
365
+ const mappedCode = BETTER_AUTH_ERROR_MAP[betterError.code];
366
+ if (mappedCode) {
367
+ const def$2 = getErrorDefinition(mappedCode);
368
+ return createNormalizedError(def$2.message, def$2.status, def$2.code, status);
369
+ }
370
+ }
371
+ const def$1 = getErrorDefinition(mapStatusCodeToErrorCode(status, betterError.message || betterError.statusText));
372
+ return createNormalizedError(betterError.message || def$1.message, status, def$1.code, status);
373
+ }
374
+ if (error instanceof Error) {
375
+ const def$1 = getErrorDefinition(mapMessageToErrorCode(error.message));
376
+ return createNormalizedError(error.message || def$1.message, def$1.status, def$1.code, def$1.status);
377
+ }
378
+ const def = getErrorDefinition(AuthErrorCode.UnknownError);
379
+ return new AuthError(def.message, def.status, def.code);
380
+ }
381
+ /**
382
+ * Map HTTP status code to AuthErrorCode
383
+ * Uses message content for disambiguation when status code is ambiguous
384
+ */
385
+ function mapStatusCodeToErrorCode(status, message) {
386
+ const lowerMessage = message?.toLowerCase() || "";
387
+ switch (status) {
388
+ case 401:
389
+ if (lowerMessage.includes("token") || lowerMessage.includes("jwt")) return AuthErrorCode.BadJwt;
390
+ if (lowerMessage.includes("session")) return AuthErrorCode.SessionNotFound;
391
+ if (lowerMessage.includes("expired")) return AuthErrorCode.SessionExpired;
392
+ return AuthErrorCode.InvalidCredentials;
393
+ case 404:
394
+ if (lowerMessage.includes("identity") || lowerMessage.includes("account")) return AuthErrorCode.IdentityNotFound;
395
+ if (lowerMessage.includes("session")) return AuthErrorCode.SessionNotFound;
396
+ return AuthErrorCode.UserNotFound;
397
+ case 409:
398
+ if (lowerMessage.includes("email")) return AuthErrorCode.EmailExists;
399
+ if (lowerMessage.includes("phone")) return AuthErrorCode.PhoneExists;
400
+ return AuthErrorCode.UserAlreadyExists;
401
+ case 422:
402
+ if (lowerMessage.includes("email") && lowerMessage.includes("confirm")) return AuthErrorCode.EmailNotConfirmed;
403
+ if (lowerMessage.includes("phone") && lowerMessage.includes("confirm")) return AuthErrorCode.PhoneNotConfirmed;
404
+ return AuthErrorCode.ValidationFailed;
405
+ case 429:
406
+ if (lowerMessage.includes("email")) return AuthErrorCode.OverEmailSendRateLimit;
407
+ if (lowerMessage.includes("sms") || lowerMessage.includes("phone")) return AuthErrorCode.OverSmsSendRateLimit;
408
+ return AuthErrorCode.OverRequestRateLimit;
409
+ case 400:
410
+ if (lowerMessage.includes("password") && lowerMessage.includes("weak")) return AuthErrorCode.WeakPassword;
411
+ if (lowerMessage.includes("email") && lowerMessage.includes("invalid")) return AuthErrorCode.EmailAddressInvalid;
412
+ if (lowerMessage.includes("json")) return AuthErrorCode.BadJson;
413
+ if (lowerMessage.includes("oauth") || lowerMessage.includes("callback")) return AuthErrorCode.BadOAuthCallback;
414
+ return AuthErrorCode.ValidationFailed;
415
+ case 403:
416
+ if (lowerMessage.includes("provider") || lowerMessage.includes("oauth")) return AuthErrorCode.OAuthProviderNotSupported;
417
+ if (lowerMessage.includes("phone")) return AuthErrorCode.PhoneProviderDisabled;
418
+ if (lowerMessage.includes("sso")) return AuthErrorCode.SsoProviderDisabled;
419
+ return AuthErrorCode.FeatureNotSupported;
420
+ case 501: return AuthErrorCode.NotImplemented;
421
+ case 503: return AuthErrorCode.FeatureNotSupported;
422
+ default:
423
+ if (lowerMessage.includes("oauth")) return AuthErrorCode.OAuthCallbackFailed;
424
+ return AuthErrorCode.UnexpectedFailure;
425
+ }
426
+ }
427
+ /**
428
+ * Map error message content to AuthErrorCode
429
+ * Used as fallback when status code is not available
430
+ */
431
+ function mapMessageToErrorCode(message) {
432
+ const lower = message.toLowerCase();
433
+ if (lower.includes("invalid login") || lower.includes("incorrect") || lower.includes("wrong password")) return AuthErrorCode.InvalidCredentials;
434
+ if (lower.includes("token") && (lower.includes("invalid") || lower.includes("expired"))) return AuthErrorCode.BadJwt;
435
+ if (lower.includes("session") && lower.includes("expired")) return AuthErrorCode.SessionExpired;
436
+ if (lower.includes("session") && lower.includes("not found")) return AuthErrorCode.SessionNotFound;
437
+ if (lower.includes("already exists") || lower.includes("already registered")) return AuthErrorCode.UserAlreadyExists;
438
+ if (lower.includes("not found") && lower.includes("user")) return AuthErrorCode.UserNotFound;
439
+ if (lower.includes("not found") && lower.includes("identity")) return AuthErrorCode.IdentityNotFound;
440
+ if (lower.includes("email") && lower.includes("not confirmed")) return AuthErrorCode.EmailNotConfirmed;
441
+ if (lower.includes("phone") && lower.includes("not confirmed")) return AuthErrorCode.PhoneNotConfirmed;
442
+ if (lower.includes("weak password") || lower.includes("password") && lower.includes("requirements")) return AuthErrorCode.WeakPassword;
443
+ if (lower.includes("email") && lower.includes("invalid")) return AuthErrorCode.EmailAddressInvalid;
444
+ if (lower.includes("rate limit") || lower.includes("too many requests")) return AuthErrorCode.OverRequestRateLimit;
445
+ if (lower.includes("oauth") && lower.includes("failed")) return AuthErrorCode.OAuthCallbackFailed;
446
+ if (lower.includes("provider") && lower.includes("not supported")) return AuthErrorCode.OAuthProviderNotSupported;
447
+ return AuthErrorCode.UnexpectedFailure;
448
+ }
449
+ /**
450
+ * Create normalized error with correct type (AuthError vs AuthApiError)
451
+ * Uses AuthApiError for non-500 status codes (API/client errors)
452
+ * Uses AuthError for 500 status codes (server errors)
453
+ */
454
+ function createNormalizedError(message, targetStatus, code, _originalStatus) {
455
+ const status = targetStatus;
456
+ if (status !== 500 && status !== 501 && status !== 503) return new AuthApiError(message, status, code);
457
+ return new AuthError(message, status, code);
458
+ }
459
+ /**
460
+ * Map Better Auth session to Session format
461
+ */
462
+ function mapBetterAuthSession(betterAuthSession, betterAuthUser) {
463
+ if (!betterAuthSession || !betterAuthUser) return null;
464
+ let expiresAt;
465
+ if (typeof betterAuthSession.expiresAt === "string") expiresAt = Math.floor(new Date(betterAuthSession.expiresAt).getTime() / 1e3);
466
+ else if (typeof betterAuthSession.expiresAt === "object" && betterAuthSession.expiresAt instanceof Date) expiresAt = Math.floor(betterAuthSession.expiresAt.getTime() / 1e3);
467
+ else expiresAt = Math.floor(Date.now() / 1e3) + Math.floor(DEFAULT_SESSION_EXPIRY_MS / 1e3);
468
+ const now = Math.floor(Date.now() / 1e3);
469
+ const expiresIn = Math.max(0, expiresAt - now);
470
+ return {
471
+ access_token: betterAuthSession.token,
472
+ refresh_token: "",
473
+ expires_at: expiresAt,
474
+ expires_in: expiresIn,
475
+ token_type: "bearer",
476
+ user: mapBetterAuthUser(betterAuthUser)
477
+ };
478
+ }
479
+ /**
480
+ * Map Better Auth user to User format
481
+ */
482
+ function mapBetterAuthUser(betterAuthUser) {
483
+ const createdAt = toISOString(betterAuthUser.createdAt);
484
+ const updatedAt = toISOString(betterAuthUser.updatedAt);
485
+ const userMetadata = {};
486
+ if (betterAuthUser.name) userMetadata.displayName = betterAuthUser.name;
487
+ if (betterAuthUser.image) userMetadata.profileImageUrl = betterAuthUser.image;
488
+ const userRecord = betterAuthUser;
489
+ for (const key of Object.keys(userRecord)) if (![
490
+ "id",
491
+ "email",
492
+ "emailVerified",
493
+ "name",
494
+ "image",
495
+ "createdAt",
496
+ "updatedAt"
497
+ ].includes(key)) userMetadata[key] = userRecord[key];
498
+ return {
499
+ id: betterAuthUser.id,
500
+ email: betterAuthUser.email || "",
501
+ email_confirmed_at: betterAuthUser.emailVerified ? createdAt : void 0,
502
+ phone: void 0,
503
+ confirmed_at: betterAuthUser.emailVerified ? createdAt : void 0,
504
+ last_sign_in_at: updatedAt,
505
+ app_metadata: {},
506
+ user_metadata: userMetadata,
507
+ identities: [],
508
+ created_at: createdAt,
509
+ updated_at: updatedAt,
510
+ aud: "authenticated",
511
+ role: "authenticated"
512
+ };
513
+ }
514
+ function mapBetterAuthIdentity(betterAuthUserIdentityAccount, accountInfoData) {
515
+ return {
516
+ id: betterAuthUserIdentityAccount.id,
517
+ user_id: betterAuthUserIdentityAccount.id,
518
+ identity_id: betterAuthUserIdentityAccount.accountId,
519
+ provider: betterAuthUserIdentityAccount.providerId,
520
+ created_at: toISOString(betterAuthUserIdentityAccount.createdAt),
521
+ updated_at: toISOString(betterAuthUserIdentityAccount.updatedAt),
522
+ last_sign_in_at: toISOString(betterAuthUserIdentityAccount.updatedAt),
523
+ identity_data: accountInfoData ? {
524
+ provider: betterAuthUserIdentityAccount.providerId,
525
+ provider_id: betterAuthUserIdentityAccount.accountId,
526
+ scopes: betterAuthUserIdentityAccount.scopes,
527
+ email: accountInfoData.data.email,
528
+ name: accountInfoData.data.user.name,
529
+ picture: accountInfoData.data.user.picture,
530
+ email_verified: accountInfoData.data.user.email_verified,
531
+ ...accountInfoData.data
532
+ } : {
533
+ provider: betterAuthUserIdentityAccount.providerId,
534
+ provider_id: betterAuthUserIdentityAccount.accountId,
535
+ scopes: betterAuthUserIdentityAccount.scopes
536
+ }
537
+ };
538
+ }
539
+
540
+ //#endregion
541
+ export { createAuthError as a, isAuthApiError as c, NEON_AUTH_POPUP_CALLBACK_PARAM_NAME as d, NEON_AUTH_POPUP_CALLBACK_ROUTE as f, SESSION_CACHE_TTL_MS as g, OAUTH_POPUP_MESSAGE_TYPE as h, AuthErrorCode as i, isAuthError as l, NEON_AUTH_SESSION_VERIFIER_PARAM_NAME as m, mapBetterAuthSession as n, AuthApiError as o, NEON_AUTH_POPUP_PARAM_NAME as p, normalizeBetterAuthError as r, AuthError as s, mapBetterAuthIdentity as t, CLOCK_SKEW_BUFFER_MS as u };
@@ -1,4 +1,4 @@
1
- import { t as NeonAuthAdapterCore } from "./adapter-core-D00qcqMo.mjs";
1
+ import { t as NeonAuthAdapterCore } from "./adapter-core-BFMM3lwe.mjs";
2
2
  import { createAuthClient } from "better-auth/react";
3
3
 
4
4
  //#region src/adapters/better-auth-react/better-auth-react-adapter.ts