@neondatabase/auth 0.1.0-beta.14 → 0.1.0-beta.16

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 (43) hide show
  1. package/README.md +1 -0
  2. package/dist/{adapter-core-BPv4mLT0.mjs → adapter-core-BQ6ga1zK.mjs} +119 -20
  3. package/dist/{adapter-core-9F3bfyWA.d.mts → adapter-core-DYWYECKK.d.mts} +16 -8
  4. package/dist/{better-auth-react-adapter-BkeuhSFt.mjs → better-auth-react-adapter-BLKXYcWM.mjs} +1 -1
  5. package/dist/{supabase-adapter-_2wgvfZ3.d.mts → better-auth-react-adapter-tKs79AwE.d.mts} +204 -290
  6. package/dist/constants-2bpp2_-f.mjs +30 -0
  7. package/dist/index-B6dAIdkW.d.mts +100 -0
  8. package/dist/index.d.mts +5 -104
  9. package/dist/index.mjs +2 -1
  10. package/dist/middleware-DXwLKcbA.mjs +305 -0
  11. package/dist/neon-auth-B_otuPjh.d.mts +105 -0
  12. package/dist/{neon-auth-BhLZg9v8.mjs → neon-auth-ClDZNB9a.mjs} +1 -1
  13. package/dist/next/index.d.mts +8 -104
  14. package/dist/next/index.mjs +4 -310
  15. package/dist/next/server/index.d.mts +340 -0
  16. package/dist/next/server/index.mjs +432 -0
  17. package/dist/react/adapters/index.d.mts +4 -3
  18. package/dist/react/adapters/index.mjs +2 -1
  19. package/dist/react/index.d.mts +5 -4
  20. package/dist/react/index.mjs +4 -4
  21. package/dist/react/ui/index.d.mts +1 -1
  22. package/dist/react/ui/index.mjs +2 -3
  23. package/dist/react/ui/server.mjs +2 -2
  24. package/dist/{supabase-adapter-rl2coLdb.mjs → supabase-adapter-Bl576usk.mjs} +2 -1
  25. package/dist/{better-auth-react-adapter-BYvAsZdj.d.mts → supabase-adapter-DtT0d6It.d.mts} +147 -61
  26. package/dist/types/index.d.mts +3 -7
  27. package/dist/ui/css.css +1 -1
  28. package/dist/ui/theme.css +1 -1
  29. package/dist/ui-DLtIc4wi.mjs +4 -0
  30. package/dist/vanilla/adapters/index.d.mts +4 -3
  31. package/dist/vanilla/adapters/index.mjs +2 -1
  32. package/dist/vanilla/index.d.mts +4 -3
  33. package/dist/vanilla/index.mjs +2 -1
  34. package/llms.txt +157 -0
  35. package/package.json +7 -2
  36. package/dist/chunk-5DLVHPZS-Bxj7snpZ-EhdAQJMu.mjs +0 -533
  37. package/dist/ui-C1IRQzLY.mjs +0 -9449
  38. /package/dist/{adapters-D0mxG3F-.mjs → adapters-CUvhsAvY.mjs} +0 -0
  39. /package/dist/{adapters-Df6Dd3KK.mjs → adapters-CivF9wql.mjs} +0 -0
  40. /package/dist/{better-auth-types-CE4hLv9E.d.mts → better-auth-types-Kq3kGuiz.d.mts} +0 -0
  41. /package/dist/{index-ClXLQ1fw.d.mts → index-D8dPsry7.d.mts} +0 -0
  42. /package/dist/{index-BXlAjlSt.d.mts → index-D_HDtZfY.d.mts} +0 -0
  43. /package/dist/{index-DCQ5Y2ED.d.mts → index-OEBbnNdr.d.mts} +0 -0
@@ -0,0 +1,30 @@
1
+ //#region src/core/constants.ts
2
+ /**
3
+ * Session caching configuration constants
4
+ *
5
+ * Uses industry-standard 60s cache TTL (common across auth providers).
6
+ *
7
+ * Note: Token refresh detection is now automatic via Better Auth's
8
+ * fetchOptions.onSuccess callback. No polling is needed.
9
+ */
10
+ /** Session cache TTL in milliseconds (60 seconds) */
11
+ const SESSION_CACHE_TTL_MS = 6e4;
12
+ /** Clock skew buffer for token expiration checks in milliseconds (10 seconds) */
13
+ const CLOCK_SKEW_BUFFER_MS = 1e4;
14
+ /** Default session expiry duration in milliseconds (1 hour) */
15
+ const DEFAULT_SESSION_EXPIRY_MS = 36e5;
16
+ /** Name of the session verifier parameter in the URL, used for the OAUTH flow */
17
+ const NEON_AUTH_SESSION_VERIFIER_PARAM_NAME = "neon_auth_session_verifier";
18
+ /** Name of the popup marker parameter in the URL, used for OAuth popup flow in iframes */
19
+ const NEON_AUTH_POPUP_PARAM_NAME = "neon_popup";
20
+ /** Name of the original callback URL parameter, used in OAuth popup flow */
21
+ const NEON_AUTH_POPUP_CALLBACK_PARAM_NAME = "neon_popup_callback";
22
+ /** The callback route used for OAuth popup completion (must be in middleware SKIP_ROUTES) */
23
+ const NEON_AUTH_POPUP_CALLBACK_ROUTE = "/auth/callback";
24
+ /** Message type for OAuth popup completion postMessage */
25
+ const OAUTH_POPUP_MESSAGE_TYPE = "neon-auth:oauth-complete";
26
+ /** Prefix for all Neon Auth cookies */
27
+ const NEON_AUTH_COOKIE_PREFIX = "__Secure-neon-auth";
28
+
29
+ //#endregion
30
+ export { NEON_AUTH_POPUP_CALLBACK_ROUTE as a, OAUTH_POPUP_MESSAGE_TYPE as c, NEON_AUTH_POPUP_CALLBACK_PARAM_NAME as i, SESSION_CACHE_TTL_MS as l, DEFAULT_SESSION_EXPIRY_MS as n, NEON_AUTH_POPUP_PARAM_NAME as o, NEON_AUTH_COOKIE_PREFIX as r, NEON_AUTH_SESSION_VERIFIER_PARAM_NAME as s, CLOCK_SKEW_BUFFER_MS as t };
@@ -0,0 +1,100 @@
1
+ import { n as BetterAuthSession, r as BetterAuthUser } from "./better-auth-types-Kq3kGuiz.mjs";
2
+ import { NextRequest, NextResponse } from "next/server";
3
+
4
+ //#region src/next/handler/index.d.ts
5
+ type Params = {
6
+ path: string[];
7
+ };
8
+ /**
9
+ *
10
+ * An API route handler to handle the auth requests from the client and proxy them to the Neon Auth.
11
+ *
12
+ * @returns A Next.js API handler functions those can be used in a Next.js route.
13
+ *
14
+ * @example
15
+ *
16
+ * Mount the `authApiHandler` to an API route. Create a route file inside `/api/auth/[...all]/route.ts` directory.
17
+ * And add the following code:
18
+ *
19
+ * ```ts
20
+ *
21
+ * import { authApiHandler } from '@neondatabase/auth/next';
22
+ *
23
+ * export const { GET, POST } = authApiHandler();
24
+ * ```
25
+ *
26
+ */
27
+ declare function authApiHandler(): {
28
+ GET: (request: Request, {
29
+ params
30
+ }: {
31
+ params: Promise<Params>;
32
+ }) => Promise<Response>;
33
+ POST: (request: Request, {
34
+ params
35
+ }: {
36
+ params: Promise<Params>;
37
+ }) => Promise<Response>;
38
+ PUT: (request: Request, {
39
+ params
40
+ }: {
41
+ params: Promise<Params>;
42
+ }) => Promise<Response>;
43
+ DELETE: (request: Request, {
44
+ params
45
+ }: {
46
+ params: Promise<Params>;
47
+ }) => Promise<Response>;
48
+ PATCH: (request: Request, {
49
+ params
50
+ }: {
51
+ params: Promise<Params>;
52
+ }) => Promise<Response>;
53
+ };
54
+ //#endregion
55
+ //#region src/next/middleware/index.d.ts
56
+ type NeonAuthMiddlewareOptions = {
57
+ loginUrl?: string;
58
+ };
59
+ /**
60
+ * A Next.js middleware to protect routes from unauthenticated requests and refresh the session if required.
61
+ *
62
+ * @param loginUrl - The URL to redirect to when the user is not authenticated.
63
+ * @returns A middleware function that can be used in the Next.js app.
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * import { neonAuthMiddleware } from "@neondatabase/auth/next"
68
+ *
69
+ * export default neonAuthMiddleware({
70
+ * loginUrl: '/auth/sign-in',
71
+ * });
72
+ * ```
73
+ */
74
+ declare function neonAuthMiddleware({
75
+ loginUrl
76
+ }: NeonAuthMiddlewareOptions): (request: NextRequest) => Promise<NextResponse<unknown>>;
77
+ //#endregion
78
+ //#region src/next/auth/session.d.ts
79
+ type SessionData = {
80
+ session: BetterAuthSession;
81
+ user: BetterAuthUser;
82
+ } | {
83
+ session: null;
84
+ user: null;
85
+ };
86
+ /**
87
+ * A utility function to be used in react server components fetch the session details from the Neon Auth API, if session token is available in cookie.
88
+ *
89
+ * @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import { neonAuth } from "@neondatabase/auth/next"
94
+ *
95
+ * const { session, user } = await neonAuth()
96
+ * ```
97
+ */
98
+ declare const neonAuth: () => Promise<SessionData>;
99
+ //#endregion
100
+ export { neonAuthMiddleware as n, authApiHandler as r, neonAuth as t };
package/dist/index.d.mts CHANGED
@@ -1,105 +1,6 @@
1
- import { r as SupportedBetterAuthClientPlugins } from "./adapter-core-9F3bfyWA.mjs";
2
- import { r as BetterAuthReactAdapterInstance } from "./better-auth-react-adapter-BYvAsZdj.mjs";
3
- import { r as SupabaseAuthAdapterInstance, s as BetterAuthVanillaAdapterInstance } from "./supabase-adapter-_2wgvfZ3.mjs";
4
- import { createAuthClient as createAuthClient$1 } from "better-auth/react";
5
- import { createAuthClient as createAuthClient$2 } from "better-auth/client";
6
-
7
- //#region src/neon-auth.d.ts
8
-
9
- /**
10
- * Type representing the Better Auth React client
11
- */
12
- type ReactBetterAuthClient = ReturnType<typeof createAuthClient$1<{
13
- plugins: SupportedBetterAuthClientPlugins;
14
- }>>;
15
- /**`
16
- * Type representing the Better Auth Vanilla client
17
- */
18
- type VanillaBetterAuthClient = ReturnType<typeof createAuthClient$2<{
19
- plugins: SupportedBetterAuthClientPlugins;
20
- }>>;
21
- /**
22
- * Union type of all supported auth adapter instances
23
- */
24
- type NeonAuthAdapter = BetterAuthVanillaAdapterInstance | BetterAuthReactAdapterInstance | SupabaseAuthAdapterInstance;
25
- /**
26
- * Configuration for createAuthClient
27
- */
28
- interface NeonAuthConfig<T extends NeonAuthAdapter> {
29
- /** The adapter builder to use. Defaults to BetterAuthVanillaAdapter() if not specified. */
30
- adapter?: (url: string) => T;
31
- /**
32
- * When true, automatically uses an anonymous token when no user session exists.
33
- * This enables RLS-based data access for users with the anonymous role.
34
- * @default false
35
- */
36
- allowAnonymous?: boolean;
37
- }
38
- /**
39
- * Resolves the public API type for an adapter.
40
- * - SupabaseAuthAdapter: exposes its own methods directly (Supabase-compatible API)
41
- * - BetterAuth adapters: expose the Better Auth client directly
42
- */
43
- type NeonAuthPublicApi<T extends NeonAuthAdapter> = T extends BetterAuthVanillaAdapterInstance ? VanillaBetterAuthClient : T extends BetterAuthReactAdapterInstance ? ReactBetterAuthClient : T;
44
- /**
45
- * NeonAuth type - combines base functionality with the appropriate public API
46
- * This is the return type of createAuthClient()
47
- *
48
- * For SupabaseAuthAdapter: exposes Supabase-compatible methods (signInWithPassword, getSession, etc.)
49
- * For BetterAuth adapters: exposes the Better Auth client directly (signIn.email, signUp.email, etc.)
50
- */
51
- type NeonAuth<T extends NeonAuthAdapter> = {
52
- adapter: NeonAuthPublicApi<T>;
53
- getJWTToken: () => Promise<string | null>;
54
- };
55
- /**
56
- * Create a NeonAuth instance that exposes the appropriate API based on the adapter.
57
- *
58
- * @param url - The auth service URL (e.g., 'https://auth.example.com')
59
- * @param config - Configuration with adapter builder
60
- * @returns NeonAuth instance with the adapter's API exposed directly
61
- *
62
- * @example SupabaseAuthAdapter - Supabase-compatible API
63
- * ```typescript
64
- * import { createAuthClient, SupabaseAuthAdapter } from '@neondatabase/auth';
65
- *
66
- * const auth = createAuthClient('https://auth.example.com', {
67
- * adapter: SupabaseAuthAdapter(),
68
- * });
69
- *
70
- * // Supabase-compatible methods
71
- * await auth.signInWithPassword({ email, password });
72
- * await auth.getSession();
73
- * ```
74
- *
75
- * @example BetterAuthVanillaAdapter - Direct Better Auth API
76
- * ```typescript
77
- * import { createAuthClient, BetterAuthVanillaAdapter } from '@neondatabase/auth';
78
- *
79
- * const auth = createAuthClient('https://auth.example.com', {
80
- * adapter: BetterAuthVanillaAdapter(),
81
- * });
82
- *
83
- * // Direct Better Auth API access
84
- * await auth.signIn.email({ email, password });
85
- * await auth.signUp.email({ email, password, name: 'John' });
86
- * await auth.getSession();
87
- * ```
88
- *
89
- * @example BetterAuthReactAdapter - Better Auth with React hooks
90
- * ```typescript
91
- * import { createAuthClient, BetterAuthReactAdapter } from '@neondatabase/auth';
92
- *
93
- * const auth = createAuthClient('https://auth.example.com', {
94
- * adapter: BetterAuthReactAdapter(),
95
- * });
96
- *
97
- * // Direct Better Auth API with React hooks
98
- * await auth.signIn.email({ email, password });
99
- * const session = auth.useSession(); // React hook
100
- * ```
101
- */
102
- declare function createInternalNeonAuth<T extends NeonAuthAdapter = BetterAuthVanillaAdapterInstance>(url: string, config?: NeonAuthConfig<T>): NeonAuth<T>;
103
- declare function createAuthClient<T extends NeonAuthAdapter = BetterAuthVanillaAdapterInstance>(url: string, config?: NeonAuthConfig<T>): NeonAuthPublicApi<T>;
104
- //#endregion
1
+ import "./better-auth-types-Kq3kGuiz.mjs";
2
+ import "./adapter-core-DYWYECKK.mjs";
3
+ import "./better-auth-react-adapter-tKs79AwE.mjs";
4
+ import "./supabase-adapter-DtT0d6It.mjs";
5
+ import { a as ReactBetterAuthClient, c as createInternalNeonAuth, i as NeonAuthPublicApi, n as NeonAuthAdapter, o as VanillaBetterAuthClient, r as NeonAuthConfig, s as createAuthClient, t as NeonAuth } from "./neon-auth-B_otuPjh.mjs";
105
6
  export { type NeonAuth, type NeonAuthAdapter, type NeonAuthConfig, type NeonAuthPublicApi, type ReactBetterAuthClient, type VanillaBetterAuthClient, createAuthClient, createInternalNeonAuth };
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
- import { n as createInternalNeonAuth, t as createAuthClient } from "./neon-auth-BhLZg9v8.mjs";
1
+ import "./adapter-core-BQ6ga1zK.mjs";
2
+ import { n as createInternalNeonAuth, t as createAuthClient } from "./neon-auth-ClDZNB9a.mjs";
2
3
 
3
4
  export { createAuthClient, createInternalNeonAuth };
@@ -0,0 +1,305 @@
1
+ import { r as NEON_AUTH_COOKIE_PREFIX, s as NEON_AUTH_SESSION_VERIFIER_PARAM_NAME } from "./constants-2bpp2_-f.mjs";
2
+ import { parseCookies, parseSetCookieHeader } from "better-auth/cookies";
3
+ import { NextRequest, NextResponse } from "next/server";
4
+ import { cookies, headers } from "next/headers";
5
+
6
+ //#region src/next/errors.ts
7
+ const ERRORS = { MISSING_AUTH_BASE_URL: "Missing environment variable: NEON_AUTH_BASE_URL. \n You must provide the auth url of your Neon Auth instance in environment variables" };
8
+
9
+ //#endregion
10
+ //#region src/utils/cookies.ts
11
+ /**
12
+ * Extract the Neon Auth cookies from the request headers.
13
+ * Only returns cookies that start with the NEON_AUTH_COOKIE_PREFIX.
14
+ *
15
+ * @param headers - The request headers or cookie header string.
16
+ * @returns The cookie string with all Neon Auth cookies (e.g., "name=value; name2=value2").
17
+ */
18
+ const extractNeonAuthCookies = (headers$1) => {
19
+ const cookieHeader = typeof headers$1 === "string" ? headers$1 : headers$1.get("cookie");
20
+ if (!cookieHeader) return "";
21
+ const parsedCookies = parseCookies(cookieHeader);
22
+ const result = [];
23
+ for (const [name, value] of parsedCookies.entries()) if (name.startsWith(NEON_AUTH_COOKIE_PREFIX)) result.push(`${name}=${value}`);
24
+ return result.join("; ");
25
+ };
26
+ /**
27
+ * Parses the `set-cookie` header from Neon Auth response into a list of cookies.
28
+ *
29
+ * @param setCookieHeader - The `set-cookie` header from Neon Auth response.
30
+ * @returns The list of parsed cookies with their options.
31
+ */
32
+ const parseSetCookies = (setCookieHeader) => {
33
+ const parsedCookies = parseSetCookieHeader(setCookieHeader);
34
+ const cookies$1 = [];
35
+ for (const entry of parsedCookies.entries()) {
36
+ const [name, parsedCookie] = entry;
37
+ cookies$1.push({
38
+ name,
39
+ value: decodeURIComponent(parsedCookie.value),
40
+ path: parsedCookie.path,
41
+ maxAge: parsedCookie["max-age"] ?? parsedCookie.maxAge,
42
+ httpOnly: parsedCookie.httponly ?? true,
43
+ secure: parsedCookie.secure ?? true,
44
+ sameSite: parsedCookie.samesite ?? "lax",
45
+ partitioned: parsedCookie.partitioned
46
+ });
47
+ }
48
+ return cookies$1;
49
+ };
50
+
51
+ //#endregion
52
+ //#region src/next/constants.ts
53
+ const NEON_AUTH_SESSION_COOKIE_NAME = `${NEON_AUTH_COOKIE_PREFIX}.session_token`;
54
+ const NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME = `${NEON_AUTH_COOKIE_PREFIX}.session_challange`;
55
+ const NEON_AUTH_HEADER_MIDDLEWARE_NAME = "X-Neon-Auth-Next-Middleware";
56
+
57
+ //#endregion
58
+ //#region src/next/handler/request.ts
59
+ const PROXY_HEADERS = [
60
+ "user-agent",
61
+ "authorization",
62
+ "referer",
63
+ "content-type"
64
+ ];
65
+ const handleAuthRequest = async (baseUrl, request, path) => {
66
+ const headers$1 = prepareRequestHeaders(request);
67
+ const body = await parseRequestBody(request);
68
+ try {
69
+ const upstreamURL = getUpstreamURL(baseUrl, path, { originalUrl: new URL(request.url) });
70
+ return await fetch(upstreamURL.toString(), {
71
+ method: request.method,
72
+ headers: headers$1,
73
+ body
74
+ });
75
+ } catch (error) {
76
+ const message = error instanceof Error ? error.message : "Internal Server Error";
77
+ console.error(`[AuthError] ${message}`, error);
78
+ return new Response(`[AuthError] ${message}`, { status: 500 });
79
+ }
80
+ };
81
+ const getUpstreamURL = (baseUrl, path, { originalUrl }) => {
82
+ const url = new URL(`${baseUrl}/${path}`);
83
+ if (originalUrl) {
84
+ url.search = originalUrl.search;
85
+ return url;
86
+ }
87
+ return url;
88
+ };
89
+ const prepareRequestHeaders = (request) => {
90
+ const headers$1 = new Headers();
91
+ for (const header of PROXY_HEADERS) if (request.headers.get(header)) headers$1.set(header, request.headers.get(header));
92
+ headers$1.set("Origin", getOrigin(request));
93
+ headers$1.set("Cookie", extractNeonAuthCookies(request.headers));
94
+ headers$1.set(NEON_AUTH_HEADER_MIDDLEWARE_NAME, "true");
95
+ return headers$1;
96
+ };
97
+ const getOrigin = (request) => {
98
+ return request.headers.get("origin") || request.headers.get("referer")?.split("/").slice(0, 3).join("/") || new URL(request.url).origin;
99
+ };
100
+ const parseRequestBody = async (request) => {
101
+ if (request.body) return request.text();
102
+ };
103
+
104
+ //#endregion
105
+ //#region src/next/handler/response.ts
106
+ const RESPONSE_HEADERS_ALLOWLIST = [
107
+ "content-type",
108
+ "content-length",
109
+ "content-encoding",
110
+ "transfer-encoding",
111
+ "connection",
112
+ "date",
113
+ "set-cookie",
114
+ "set-auth-jwt",
115
+ "set-auth-token",
116
+ "x-neon-ret-request-id"
117
+ ];
118
+ const handleAuthResponse = async (response) => {
119
+ return new Response(response.body, {
120
+ status: response.status,
121
+ statusText: response.statusText,
122
+ headers: prepareResponseHeaders(response)
123
+ });
124
+ };
125
+ const prepareResponseHeaders = (response) => {
126
+ const headers$1 = new Headers();
127
+ for (const header of RESPONSE_HEADERS_ALLOWLIST) {
128
+ const value = response.headers.get(header);
129
+ if (value) headers$1.set(header, value);
130
+ }
131
+ return headers$1;
132
+ };
133
+
134
+ //#endregion
135
+ //#region src/next/handler/index.ts
136
+ /**
137
+ *
138
+ * An API route handler to handle the auth requests from the client and proxy them to the Neon Auth.
139
+ *
140
+ * @returns A Next.js API handler functions those can be used in a Next.js route.
141
+ *
142
+ * @example
143
+ *
144
+ * Mount the `authApiHandler` to an API route. Create a route file inside `/api/auth/[...all]/route.ts` directory.
145
+ * And add the following code:
146
+ *
147
+ * ```ts
148
+ *
149
+ * import { authApiHandler } from '@neondatabase/auth/next';
150
+ *
151
+ * export const { GET, POST } = authApiHandler();
152
+ * ```
153
+ *
154
+ */
155
+ function authApiHandler() {
156
+ const baseURL = process.env.NEON_AUTH_BASE_URL;
157
+ if (!baseURL) throw new Error(ERRORS.MISSING_AUTH_BASE_URL);
158
+ const handler = async (request, { params }) => {
159
+ return await handleAuthResponse(await handleAuthRequest(baseURL, request, (await params).path.join("/")));
160
+ };
161
+ return {
162
+ GET: handler,
163
+ POST: handler,
164
+ PUT: handler,
165
+ DELETE: handler,
166
+ PATCH: handler
167
+ };
168
+ }
169
+
170
+ //#endregion
171
+ //#region src/next/auth/cookies.ts
172
+ /**
173
+ * Extract the Neon Auth cookies from the response headers.
174
+ * @deprecated Use parseSetCookies instead
175
+ */
176
+ const extractResponseCookies = (headers$1) => {
177
+ const cookieHeader = headers$1.get("set-cookie");
178
+ if (!cookieHeader) return [];
179
+ return cookieHeader.split(", ").map((c) => c.trim());
180
+ };
181
+
182
+ //#endregion
183
+ //#region src/next/middleware/oauth.ts
184
+ const needsSessionVerification = (request) => {
185
+ const hasVerifier = request.nextUrl.searchParams.has(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
186
+ const hasChallenge = request.cookies.get(NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME);
187
+ return hasVerifier && hasChallenge;
188
+ };
189
+ const exchangeOAuthToken = async (request, baseUrl) => {
190
+ const url = request.nextUrl;
191
+ const verifier = url.searchParams.get(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
192
+ const challenge = request.cookies.get(NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME);
193
+ if (!verifier || !challenge) return null;
194
+ const response = await handleAuthResponse(await handleAuthRequest(baseUrl, new Request(request.url, {
195
+ method: "GET",
196
+ headers: request.headers
197
+ }), "get-session"));
198
+ if (response.ok) {
199
+ const headers$1 = new Headers();
200
+ const cookies$1 = extractResponseCookies(response.headers);
201
+ for (const cookie of cookies$1) headers$1.append("Set-Cookie", cookie);
202
+ url.searchParams.delete(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
203
+ return NextResponse.redirect(url, { headers: headers$1 });
204
+ }
205
+ return null;
206
+ };
207
+
208
+ //#endregion
209
+ //#region src/next/env-variables.ts
210
+ const NEON_AUTH_BASE_URL = process.env.NEON_AUTH_BASE_URL;
211
+
212
+ //#endregion
213
+ //#region src/next/auth/session.ts
214
+ /**
215
+ * A utility function to be used in react server components fetch the session details from the Neon Auth API, if session token is available in cookie.
216
+ *
217
+ * @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
218
+ *
219
+ * @example
220
+ * ```ts
221
+ * import { neonAuth } from "@neondatabase/auth/next"
222
+ *
223
+ * const { session, user } = await neonAuth()
224
+ * ```
225
+ */
226
+ const neonAuth = async () => {
227
+ return await fetchSession();
228
+ };
229
+ /**
230
+ * A utility function to fetch the session details from the Neon Auth API, if session token is available in cookie.
231
+ *
232
+ * @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
233
+ */
234
+ const fetchSession = async () => {
235
+ const baseUrl = NEON_AUTH_BASE_URL;
236
+ const requestHeaders = await headers();
237
+ const upstreamURL = getUpstreamURL(baseUrl, "get-session", { originalUrl: new URL("get-session", baseUrl) });
238
+ const response = await fetch(upstreamURL.toString(), {
239
+ method: "GET",
240
+ headers: { Cookie: extractNeonAuthCookies(requestHeaders) }
241
+ });
242
+ const body = await response.json();
243
+ const cookieHeader = response.headers.get("set-cookie");
244
+ if (cookieHeader) {
245
+ const cookieStore = await cookies();
246
+ parseSetCookies(cookieHeader).map((cookie) => {
247
+ cookieStore.set(cookie.name, cookie.value, cookie);
248
+ });
249
+ }
250
+ if (!response.ok || body === null) return {
251
+ session: null,
252
+ user: null
253
+ };
254
+ return {
255
+ session: body.session,
256
+ user: body.user
257
+ };
258
+ };
259
+
260
+ //#endregion
261
+ //#region src/next/middleware/index.ts
262
+ const SKIP_ROUTES = [
263
+ "/api/auth",
264
+ "/auth/callback",
265
+ "/auth/sign-in",
266
+ "/auth/sign-up",
267
+ "/auth/magic-link",
268
+ "/auth/email-otp",
269
+ "/auth/forgot-password"
270
+ ];
271
+ /**
272
+ * A Next.js middleware to protect routes from unauthenticated requests and refresh the session if required.
273
+ *
274
+ * @param loginUrl - The URL to redirect to when the user is not authenticated.
275
+ * @returns A middleware function that can be used in the Next.js app.
276
+ *
277
+ * @example
278
+ * ```ts
279
+ * import { neonAuthMiddleware } from "@neondatabase/auth/next"
280
+ *
281
+ * export default neonAuthMiddleware({
282
+ * loginUrl: '/auth/sign-in',
283
+ * });
284
+ * ```
285
+ */
286
+ function neonAuthMiddleware({ loginUrl = "/auth/sign-in" }) {
287
+ const baseUrl = NEON_AUTH_BASE_URL;
288
+ if (!baseUrl) throw new Error(ERRORS.MISSING_AUTH_BASE_URL);
289
+ return async (request) => {
290
+ const { pathname } = request.nextUrl;
291
+ if (pathname.startsWith(loginUrl)) return NextResponse.next();
292
+ if (needsSessionVerification(request)) {
293
+ const response = await exchangeOAuthToken(request, baseUrl);
294
+ if (response !== null) return response;
295
+ }
296
+ if (SKIP_ROUTES.some((route) => pathname.startsWith(route))) return NextResponse.next();
297
+ if ((await fetchSession()).session === null) return NextResponse.redirect(new URL(loginUrl, request.url));
298
+ const reqHeaders = new Headers(request.headers);
299
+ reqHeaders.set(NEON_AUTH_HEADER_MIDDLEWARE_NAME, "true");
300
+ return NextResponse.next({ request: { headers: reqHeaders } });
301
+ };
302
+ }
303
+
304
+ //#endregion
305
+ export { parseSetCookies as a, extractNeonAuthCookies as i, neonAuth as n, authApiHandler as r, neonAuthMiddleware as t };
@@ -0,0 +1,105 @@
1
+ import { r as SupportedBetterAuthClientPlugins } from "./adapter-core-DYWYECKK.mjs";
2
+ import { r as BetterAuthReactAdapterInstance } from "./better-auth-react-adapter-tKs79AwE.mjs";
3
+ import { r as SupabaseAuthAdapterInstance, s as BetterAuthVanillaAdapterInstance } from "./supabase-adapter-DtT0d6It.mjs";
4
+ import { createAuthClient } from "better-auth/react";
5
+ import { createAuthClient as createAuthClient$1 } from "better-auth/client";
6
+
7
+ //#region src/neon-auth.d.ts
8
+
9
+ /**
10
+ * Type representing the Better Auth React client
11
+ */
12
+ type ReactBetterAuthClient = ReturnType<typeof createAuthClient<{
13
+ plugins: SupportedBetterAuthClientPlugins;
14
+ }>>;
15
+ /**`
16
+ * Type representing the Better Auth Vanilla client
17
+ */
18
+ type VanillaBetterAuthClient = ReturnType<typeof createAuthClient$1<{
19
+ plugins: SupportedBetterAuthClientPlugins;
20
+ }>>;
21
+ /**
22
+ * Union type of all supported auth adapter instances
23
+ */
24
+ type NeonAuthAdapter = BetterAuthVanillaAdapterInstance | BetterAuthReactAdapterInstance | SupabaseAuthAdapterInstance;
25
+ /**
26
+ * Configuration for createAuthClient
27
+ */
28
+ interface NeonAuthConfig<T extends NeonAuthAdapter> {
29
+ /** The adapter builder to use. Defaults to BetterAuthVanillaAdapter() if not specified. */
30
+ adapter?: (url: string) => T;
31
+ /**
32
+ * When true, automatically uses an anonymous token when no user session exists.
33
+ * This enables RLS-based data access for users with the anonymous role.
34
+ * @default false
35
+ */
36
+ allowAnonymous?: boolean;
37
+ }
38
+ /**
39
+ * Resolves the public API type for an adapter.
40
+ * - SupabaseAuthAdapter: exposes its own methods directly (Supabase-compatible API)
41
+ * - BetterAuth adapters: expose the Better Auth client directly
42
+ */
43
+ type NeonAuthPublicApi<T extends NeonAuthAdapter> = T extends BetterAuthVanillaAdapterInstance ? VanillaBetterAuthClient : T extends BetterAuthReactAdapterInstance ? ReactBetterAuthClient : T;
44
+ /**
45
+ * NeonAuth type - combines base functionality with the appropriate public API
46
+ * This is the return type of createAuthClient()
47
+ *
48
+ * For SupabaseAuthAdapter: exposes Supabase-compatible methods (signInWithPassword, getSession, etc.)
49
+ * For BetterAuth adapters: exposes the Better Auth client directly (signIn.email, signUp.email, etc.)
50
+ */
51
+ type NeonAuth<T extends NeonAuthAdapter> = {
52
+ adapter: NeonAuthPublicApi<T>;
53
+ getJWTToken: () => Promise<string | null>;
54
+ };
55
+ /**
56
+ * Create a NeonAuth instance that exposes the appropriate API based on the adapter.
57
+ *
58
+ * @param url - The auth service URL (e.g., 'https://auth.example.com')
59
+ * @param config - Configuration with adapter builder
60
+ * @returns NeonAuth instance with the adapter's API exposed directly
61
+ *
62
+ * @example SupabaseAuthAdapter - Supabase-compatible API
63
+ * ```typescript
64
+ * import { createAuthClient, SupabaseAuthAdapter } from '@neondatabase/auth';
65
+ *
66
+ * const auth = createAuthClient('https://auth.example.com', {
67
+ * adapter: SupabaseAuthAdapter(),
68
+ * });
69
+ *
70
+ * // Supabase-compatible methods
71
+ * await auth.signInWithPassword({ email, password });
72
+ * await auth.getSession();
73
+ * ```
74
+ *
75
+ * @example BetterAuthVanillaAdapter - Direct Better Auth API
76
+ * ```typescript
77
+ * import { createAuthClient, BetterAuthVanillaAdapter } from '@neondatabase/auth';
78
+ *
79
+ * const auth = createAuthClient('https://auth.example.com', {
80
+ * adapter: BetterAuthVanillaAdapter(),
81
+ * });
82
+ *
83
+ * // Direct Better Auth API access
84
+ * await auth.signIn.email({ email, password });
85
+ * await auth.signUp.email({ email, password, name: 'John' });
86
+ * await auth.getSession();
87
+ * ```
88
+ *
89
+ * @example BetterAuthReactAdapter - Better Auth with React hooks
90
+ * ```typescript
91
+ * import { createAuthClient, BetterAuthReactAdapter } from '@neondatabase/auth';
92
+ *
93
+ * const auth = createAuthClient('https://auth.example.com', {
94
+ * adapter: BetterAuthReactAdapter(),
95
+ * });
96
+ *
97
+ * // Direct Better Auth API with React hooks
98
+ * await auth.signIn.email({ email, password });
99
+ * const session = auth.useSession(); // React hook
100
+ * ```
101
+ */
102
+ declare function createInternalNeonAuth<T extends NeonAuthAdapter = BetterAuthVanillaAdapterInstance>(url: string, config?: NeonAuthConfig<T>): NeonAuth<T>;
103
+ declare function createAuthClient$2<T extends NeonAuthAdapter = BetterAuthVanillaAdapterInstance>(url: string, config?: NeonAuthConfig<T>): NeonAuthPublicApi<T>;
104
+ //#endregion
105
+ export { ReactBetterAuthClient as a, createInternalNeonAuth as c, NeonAuthPublicApi as i, NeonAuthAdapter as n, VanillaBetterAuthClient as o, NeonAuthConfig as r, createAuthClient$2 as s, NeonAuth as t };
@@ -1,4 +1,4 @@
1
- import { n as BetterAuthVanillaAdapter } from "./supabase-adapter-rl2coLdb.mjs";
1
+ import { n as BetterAuthVanillaAdapter } from "./supabase-adapter-Bl576usk.mjs";
2
2
 
3
3
  //#region src/neon-auth.ts
4
4
  /**