@neondatabase/auth 0.1.0-beta.9 → 0.2.0-beta.1

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 (45) hide show
  1. package/README.md +108 -18
  2. package/dist/{adapter-core-Bw9mn_AS.d.mts → adapter-core-CnrOXh1T.d.mts} +246 -280
  3. package/dist/{adapter-core-C_NEMs0b.mjs → adapter-core-CtmnMMJ7.mjs} +392 -67
  4. package/dist/better-auth-react-adapter-DNi5PC5D.d.mts +2170 -0
  5. package/dist/{better-auth-react-adapter-BbM3jLLv.mjs → better-auth-react-adapter-Dv-o6A6O.mjs} +10 -8
  6. package/dist/{chunk-5DLVHPZS-Bxj7snpZ-DoVNlsyk.mjs → chunk-VCZJYX65-CLnrj1o7-D6ZQkcc_.mjs} +13 -3
  7. package/dist/constants-Cupc_bln.mjs +28 -0
  8. package/dist/index.d.mts +4 -98
  9. package/dist/index.mjs +2 -1
  10. package/dist/neon-auth-BEGCfAe6.d.mts +107 -0
  11. package/dist/{neon-auth-DdlToh7_.mjs → neon-auth-Cs2cWh1B.mjs} +7 -4
  12. package/dist/next/index.d.mts +61 -170
  13. package/dist/next/index.mjs +4 -311
  14. package/dist/next/server/index.d.mts +538 -0
  15. package/dist/next/server/index.mjs +1373 -0
  16. package/dist/react/adapters/index.d.mts +4 -4
  17. package/dist/react/adapters/index.mjs +2 -1
  18. package/dist/react/index.d.mts +5 -5
  19. package/dist/react/index.mjs +4 -3
  20. package/dist/react/ui/index.d.mts +1 -1
  21. package/dist/react/ui/index.mjs +2 -2
  22. package/dist/react/ui/server.mjs +1 -1
  23. package/dist/{supabase-adapter-CAqbpOC7.mjs → supabase-adapter-BlcGPyOf.mjs} +28 -45
  24. package/dist/supabase-adapter-DUqw2fw8.d.mts +2258 -0
  25. package/dist/types/index.d.mts +2 -7
  26. package/dist/ui/.safelist.html +3 -0
  27. package/dist/ui/css.css +2 -2
  28. package/dist/ui/tailwind.css +2 -1
  29. package/dist/ui/theme-inline.css +44 -0
  30. package/dist/ui/theme.css +103 -76
  31. package/dist/{ui-aMoA-9nq.mjs → ui-COLWzDsu.mjs} +6024 -3004
  32. package/dist/vanilla/adapters/index.d.mts +3 -3
  33. package/dist/vanilla/adapters/index.mjs +2 -1
  34. package/dist/vanilla/index.d.mts +3 -3
  35. package/dist/vanilla/index.mjs +2 -1
  36. package/llms.txt +330 -0
  37. package/package.json +17 -10
  38. package/dist/better-auth-react-adapter-JoscqoDc.d.mts +0 -722
  39. package/dist/better-auth-types-CE4hLv9E.d.mts +0 -9
  40. package/dist/supabase-adapter-Clxlqg1x.d.mts +0 -127
  41. /package/dist/{adapters-D0mxG3F-.mjs → adapters-B7YKkjaL.mjs} +0 -0
  42. /package/dist/{adapters-Df6Dd3KK.mjs → adapters-CivF9wql.mjs} +0 -0
  43. /package/dist/{index-ClXLQ1fw.d.mts → index-CPnFzULh.d.mts} +0 -0
  44. /package/dist/{index-BXlAjlSt.d.mts → index-CzsGMS7C.d.mts} +0 -0
  45. /package/dist/{index-DCQ5Y2ED.d.mts → index-OEBbnNdr.d.mts} +0 -0
@@ -1,4 +1,4 @@
1
- import "../../adapter-core-Bw9mn_AS.mjs";
2
- import { a as BetterAuthVanillaAdapter, c as BetterAuthVanillaAdapterOptions, i as SupabaseAuthAdapterOptions, n as SupabaseAuthAdapterBuilder, o as BetterAuthVanillaAdapterBuilder, r as SupabaseAuthAdapterInstance, s as BetterAuthVanillaAdapterInstance, t as SupabaseAuthAdapter } from "../../supabase-adapter-Clxlqg1x.mjs";
3
- import "../../index-ClXLQ1fw.mjs";
1
+ import "../../adapter-core-CnrOXh1T.mjs";
2
+ import { a as BetterAuthVanillaAdapter, c as BetterAuthVanillaAdapterOptions, i as SupabaseAuthAdapterOptions, n as SupabaseAuthAdapterBuilder, o as BetterAuthVanillaAdapterBuilder, r as SupabaseAuthAdapterInstance, s as BetterAuthVanillaAdapterInstance, t as SupabaseAuthAdapter } from "../../supabase-adapter-DUqw2fw8.mjs";
3
+ import "../../index-OEBbnNdr.mjs";
4
4
  export { BetterAuthVanillaAdapter, BetterAuthVanillaAdapterBuilder, BetterAuthVanillaAdapterInstance, BetterAuthVanillaAdapterOptions, SupabaseAuthAdapter, SupabaseAuthAdapterBuilder, SupabaseAuthAdapterInstance, SupabaseAuthAdapterOptions };
@@ -1,3 +1,4 @@
1
- import { n as BetterAuthVanillaAdapter, t as SupabaseAuthAdapter } from "../../supabase-adapter-CAqbpOC7.mjs";
1
+ import "../../adapter-core-CtmnMMJ7.mjs";
2
+ import { n as BetterAuthVanillaAdapter, t as SupabaseAuthAdapter } from "../../supabase-adapter-BlcGPyOf.mjs";
2
3
 
3
4
  export { BetterAuthVanillaAdapter, SupabaseAuthAdapter };
@@ -1,4 +1,4 @@
1
- import "../adapter-core-Bw9mn_AS.mjs";
2
- import { a as BetterAuthVanillaAdapter, c as BetterAuthVanillaAdapterOptions, i as SupabaseAuthAdapterOptions, n as SupabaseAuthAdapterBuilder, o as BetterAuthVanillaAdapterBuilder, r as SupabaseAuthAdapterInstance, s as BetterAuthVanillaAdapterInstance, t as SupabaseAuthAdapter } from "../supabase-adapter-Clxlqg1x.mjs";
3
- import "../index-ClXLQ1fw.mjs";
1
+ import "../adapter-core-CnrOXh1T.mjs";
2
+ import { a as BetterAuthVanillaAdapter, c as BetterAuthVanillaAdapterOptions, i as SupabaseAuthAdapterOptions, n as SupabaseAuthAdapterBuilder, o as BetterAuthVanillaAdapterBuilder, r as SupabaseAuthAdapterInstance, s as BetterAuthVanillaAdapterInstance, t as SupabaseAuthAdapter } from "../supabase-adapter-DUqw2fw8.mjs";
3
+ import "../index-OEBbnNdr.mjs";
4
4
  export { BetterAuthVanillaAdapter, BetterAuthVanillaAdapterBuilder, BetterAuthVanillaAdapterInstance, BetterAuthVanillaAdapterOptions, SupabaseAuthAdapter, SupabaseAuthAdapterBuilder, SupabaseAuthAdapterInstance, SupabaseAuthAdapterOptions };
@@ -1,3 +1,4 @@
1
- import { n as BetterAuthVanillaAdapter, t as SupabaseAuthAdapter } from "../supabase-adapter-CAqbpOC7.mjs";
1
+ import "../adapter-core-CtmnMMJ7.mjs";
2
+ import { n as BetterAuthVanillaAdapter, t as SupabaseAuthAdapter } from "../supabase-adapter-BlcGPyOf.mjs";
2
3
 
3
4
  export { BetterAuthVanillaAdapter, SupabaseAuthAdapter };
package/llms.txt ADDED
@@ -0,0 +1,330 @@
1
+ # @neondatabase/auth
2
+
3
+ > TypeScript SDK for Neon Auth - authentication adapters for PostgreSQL with session caching, request deduplication, and optional anonymous access.
4
+
5
+ `@neondatabase/auth` provides authentication for applications using Neon Auth. It uses the Better Auth API by default, with optional adapters for different API styles (Supabase-compatible, React hooks).
6
+
7
+ ## When to Use This Package
8
+
9
+ | Use Case | Package |
10
+ |----------|---------|
11
+ | Auth only (no database queries) | `@neondatabase/auth` |
12
+ | Auth + Database queries | `@neondatabase/neon-js` (includes this package) |
13
+ | Pre-built UI components | Add `@neondatabase/auth-ui` |
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @neondatabase/auth
19
+ ```
20
+
21
+ ## Environment Variables
22
+
23
+ ```bash
24
+ # React/Vite
25
+ VITE_NEON_AUTH_URL=https://your-project.neon.tech/auth
26
+
27
+ # Next.js
28
+ NEON_AUTH_BASE_URL=https://your-project.neon.tech
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ```typescript
34
+ import { createAuthClient } from '@neondatabase/auth';
35
+
36
+ const auth = createAuthClient('https://your-auth-server.com');
37
+
38
+ // Sign up
39
+ await auth.signUp.email({
40
+ email: 'user@example.com',
41
+ password: 'secure-password',
42
+ name: 'John Doe',
43
+ });
44
+
45
+ // Sign in
46
+ await auth.signIn.email({
47
+ email: 'user@example.com',
48
+ password: 'secure-password',
49
+ });
50
+
51
+ // Get session
52
+ const session = await auth.getSession();
53
+
54
+ // Sign out
55
+ await auth.signOut();
56
+ ```
57
+
58
+ ## OAuth Authentication
59
+
60
+ ```typescript
61
+ await auth.signIn.social({
62
+ provider: 'google',
63
+ callbackURL: '/dashboard',
64
+ });
65
+ ```
66
+
67
+ ## Choosing an Adapter
68
+
69
+ | Adapter | Use When |
70
+ |---------|----------|
71
+ | Default (no adapter) | New projects, prefer Better Auth API |
72
+ | `SupabaseAuthAdapter` | Migrating from Supabase, familiar API |
73
+ | `BetterAuthReactAdapter` | Need React hooks (`useSession`) |
74
+ | `BetterAuthVanillaAdapter` | Better Auth API without React |
75
+
76
+ **Critical:** Adapters are factory functions - must call with `()`.
77
+
78
+ ## Adapters
79
+
80
+ ### SupabaseAuthAdapter
81
+
82
+ Supabase-compatible API for migrations:
83
+
84
+ ```typescript
85
+ import { createAuthClient } from '@neondatabase/auth';
86
+ import { SupabaseAuthAdapter } from '@neondatabase/auth/vanilla/adapters';
87
+
88
+ const auth = createAuthClient('https://your-auth-server.com', {
89
+ adapter: SupabaseAuthAdapter(), // Must call with ()
90
+ });
91
+
92
+ await auth.signUp({
93
+ email: 'user@example.com',
94
+ password: 'secure-password',
95
+ options: { data: { name: 'John Doe' } },
96
+ });
97
+
98
+ await auth.signInWithPassword({
99
+ email: 'user@example.com',
100
+ password: 'secure-password',
101
+ });
102
+
103
+ await auth.signInWithOAuth({
104
+ provider: 'google',
105
+ options: { redirectTo: '/dashboard' },
106
+ });
107
+
108
+ const { data: session } = await auth.getSession();
109
+ ```
110
+
111
+ ### BetterAuthVanillaAdapter
112
+
113
+ Direct Better Auth API without React:
114
+
115
+ ```typescript
116
+ import { createAuthClient } from '@neondatabase/auth';
117
+ import { BetterAuthVanillaAdapter } from '@neondatabase/auth/vanilla/adapters';
118
+
119
+ const auth = createAuthClient('https://your-auth-server.com', {
120
+ adapter: BetterAuthVanillaAdapter(),
121
+ });
122
+
123
+ await auth.signIn.email({ email, password });
124
+ const session = await auth.getSession();
125
+ ```
126
+
127
+ ### BetterAuthReactAdapter
128
+
129
+ React hooks support:
130
+
131
+ ```typescript
132
+ import { createAuthClient } from '@neondatabase/auth';
133
+ import { BetterAuthReactAdapter } from '@neondatabase/auth/react/adapters';
134
+
135
+ const auth = createAuthClient('https://your-auth-server.com', {
136
+ adapter: BetterAuthReactAdapter(),
137
+ });
138
+
139
+ function MyComponent() {
140
+ const session = auth.useSession();
141
+
142
+ if (session.isPending) return <div>Loading...</div>;
143
+ if (!session.data) return <div>Not logged in</div>;
144
+
145
+ return <div>Hello, {session.data.user.name}</div>;
146
+ }
147
+ ```
148
+
149
+ ## Anonymous Access
150
+
151
+ Enable RLS-based data access for unauthenticated users:
152
+
153
+ ```typescript
154
+ const auth = createAuthClient('https://your-auth-server.com', {
155
+ allowAnonymous: true,
156
+ });
157
+
158
+ // Returns JWT token: authenticated session → anonymous token → null
159
+ const token = await auth.getJWTToken?.();
160
+ ```
161
+
162
+ Token priority: authenticated session JWT > anonymous token > null
163
+
164
+ ## Session Behavior
165
+
166
+ **Caching:**
167
+ - Sessions cached 60s (or until JWT expires)
168
+ - `getSession()` returns cached value instantly (<1ms)
169
+ - Cache cleared synchronously on sign-out
170
+ - TTL calculated from JWT `exp` claim
171
+
172
+ **Cross-Tab Sync (browser only):**
173
+ - Sign-in/sign-out syncs across tabs via BroadcastChannel
174
+ - Automatic - no configuration needed
175
+ - Events: `SIGNED_IN`, `SIGNED_OUT`, `TOKEN_REFRESHED`, `USER_UPDATED`
176
+
177
+ **Request Deduplication:**
178
+ - Concurrent `getSession()` calls share single network request
179
+ - Prevents thundering herd on page load
180
+ - 10x faster cold starts (10 concurrent: ~2000ms → ~200ms)
181
+
182
+ ## OAuth in Iframes
183
+
184
+ SDK automatically detects iframe context and uses popup-based OAuth:
185
+ - Popup opens for OAuth provider (bypasses X-Frame-Options)
186
+ - Session passed back via postMessage
187
+ - 120s timeout with 500ms polling
188
+
189
+ No configuration needed - works automatically.
190
+
191
+ ## Error Handling
192
+
193
+ ```typescript
194
+ import { AuthError, AuthApiError } from '@neondatabase/auth';
195
+
196
+ try {
197
+ await auth.signInWithPassword({ email, password });
198
+ } catch (error) {
199
+ if (error instanceof AuthApiError) {
200
+ console.log(error.status); // HTTP status code
201
+ console.log(error.message); // Error message
202
+ console.log(error.code); // Error code if available
203
+ }
204
+ if (error instanceof AuthError) {
205
+ console.log(error.message); // Generic auth error
206
+ }
207
+ }
208
+ ```
209
+
210
+ ## API Reference
211
+
212
+ ### createAuthClient(url, config?)
213
+
214
+ - `url` - Auth service URL (required, first argument is string NOT object)
215
+ - `config.adapter` - Optional adapter factory (`SupabaseAuthAdapter()`, `BetterAuthReactAdapter()`)
216
+ - `config.allowAnonymous` - Enable anonymous tokens (default: `false`)
217
+
218
+ ### Default API (Better Auth)
219
+
220
+ - `signIn.email(credentials)` - Sign in with email/password
221
+ - `signIn.social(options)` - Sign in with OAuth provider
222
+ - `signUp.email(credentials)` - Create new user account
223
+ - `signOut()` - Sign out current user
224
+ - `getSession()` - Get current session (cached)
225
+ - `getJWTToken?.()` - Get JWT token (authenticated or anonymous)
226
+
227
+ ### SupabaseAuthAdapter API
228
+
229
+ - `signUp(credentials)` - Create user with Supabase-style options
230
+ - `signInWithPassword(credentials)` - Email/password sign in
231
+ - `signInWithOAuth(options)` - OAuth with Supabase-style options
232
+ - `getSession()` - Returns `{ data: session }`
233
+ - `getUser()` - Returns `{ data: user }`
234
+ - `updateUser(attributes)` - Update user metadata
235
+ - `resetPasswordForEmail(email, options)` - Password reset
236
+ - `onAuthStateChange(callback)` - Auth state listener (browser only)
237
+
238
+ ### BetterAuthReactAdapter API
239
+
240
+ Same as default API, plus:
241
+ - `useSession()` - React hook for session state
242
+
243
+ ## Next.js Integration
244
+
245
+ See [NEXT-JS.md](./NEXT-JS.md) for complete guide.
246
+
247
+ **Environment variables:**
248
+
249
+ ```bash
250
+ NEON_AUTH_BASE_URL=https://your-project.neon.tech
251
+ NEON_AUTH_COOKIE_SECRET=your-secret-at-least-32-characters-long
252
+ ```
253
+
254
+ **Unified server setup:**
255
+
256
+ ```typescript
257
+ // lib/auth/server.ts - Single entry point for all server functionality
258
+ import { createNeonAuth } from '@neondatabase/auth/next/server';
259
+
260
+ export const auth = createNeonAuth({
261
+ baseUrl: process.env.NEON_AUTH_BASE_URL!,
262
+ cookies: {
263
+ secret: process.env.NEON_AUTH_COOKIE_SECRET!,
264
+ sessionDataTtl: 300, // Optional: session data cache TTL in seconds (default: 300 = 5 min)
265
+ domain: '.example.com', // Optional: for cross-subdomain cookies
266
+ },
267
+ });
268
+
269
+ // app/api/auth/[...path]/route.ts - API handler
270
+ import { auth } from '@/lib/auth/server';
271
+ export const { GET, POST } = auth.handler();
272
+
273
+ // middleware.ts - Route protection
274
+ import { auth } from '@/lib/auth/server';
275
+ export default auth.middleware({ loginUrl: '/auth/sign-in' });
276
+
277
+ // lib/auth/client.ts - Client-side
278
+ "use client"
279
+ import { createAuthClient } from '@neondatabase/auth/next';
280
+ export const authClient = createAuthClient();
281
+
282
+ // Server Components
283
+ import { auth } from '@/lib/auth/server';
284
+ // Server components using `auth` methods must be rendered dynamically
285
+ export const dynamic = 'force-dynamic';
286
+ const { data: session } = await auth.getSession();
287
+
288
+ // Server Actions
289
+ import { auth } from '@/lib/auth/server';
290
+ await auth.signIn.email({ email, password });
291
+ ```
292
+
293
+ ## Performance
294
+
295
+ - **Cached `getSession()`**: <1ms (in-memory, no I/O)
296
+ - **Cold start**: ~200ms (single network request)
297
+ - **Concurrent cold start**: ~200ms total (deduplicated)
298
+ - **Token refresh**: <200ms (automatic)
299
+ - **Cross-tab sync**: <50ms (BroadcastChannel)
300
+
301
+ ## Troubleshooting
302
+
303
+ | Issue | Cause | Fix |
304
+ |-------|-------|-----|
305
+ | Session always null | Cookies blocked | Check browser settings, not incognito |
306
+ | OAuth redirect fails in iframe | X-Frame-Options | SDK uses popup automatically, allow popups |
307
+ | `adapter is not a function` | Missing `()` | Use `SupabaseAuthAdapter()` not `SupabaseAuthAdapter` |
308
+ | Cross-tab sync not working | Node.js environment | BroadcastChannel is browser-only |
309
+ | `onAuthStateChange` not firing | Not subscribed | Call returns unsubscribe function, store reference |
310
+ | Token expired immediately | Clock skew | Check server/client time sync |
311
+
312
+ ## CSS for UI Components
313
+
314
+ Choose based on your project setup:
315
+
316
+ ```css
317
+ /* Without Tailwind - pre-built bundle (~47KB) */
318
+ @import '@neondatabase/auth/ui/css';
319
+
320
+ /* With Tailwind CSS v4 - theme tokens only */
321
+ @import 'tailwindcss';
322
+ @import '@neondatabase/auth/ui/tailwind';
323
+ ```
324
+
325
+ Never import both paths - causes duplicate styles.
326
+
327
+ ## Optional
328
+
329
+ - [Next.js Integration](./NEXT-JS.md): Setup guide for Next.js 15+ with middleware and RSC support
330
+ - [Better Auth Documentation](https://www.better-auth.com/docs): Underlying auth library documentation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neondatabase/auth",
3
- "version": "0.1.0-beta.9",
3
+ "version": "0.2.0-beta.1",
4
4
  "description": "TypeScript SDK for Neon Auth - authentication for PostgreSQL with multiple adapter support",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -18,13 +18,13 @@
18
18
  "react",
19
19
  "nextjs"
20
20
  ],
21
- "homepage": "https://github.com/neondatabase-labs/neon-js/tree/main/packages/auth#readme",
21
+ "homepage": "https://github.com/neondatabase/neon-js/tree/main/packages/auth#readme",
22
22
  "bugs": {
23
- "url": "https://github.com/neondatabase-labs/neon-js/issues"
23
+ "url": "https://github.com/neondatabase/neon-js/issues"
24
24
  },
25
25
  "repository": {
26
26
  "type": "git",
27
- "url": "git+https://github.com/neondatabase-labs/neon-js.git",
27
+ "url": "git+https://github.com/neondatabase/neon-js.git",
28
28
  "directory": "packages/auth"
29
29
  },
30
30
  "funding": {
@@ -71,6 +71,10 @@
71
71
  "types": "./dist/next/index.d.mts",
72
72
  "default": "./dist/next/index.mjs"
73
73
  },
74
+ "./next/server": {
75
+ "types": "./dist/next/server/index.d.mts",
76
+ "default": "./dist/next/server/index.mjs"
77
+ },
74
78
  "./ui/css": {
75
79
  "types": "./dist/ui/css.d.ts",
76
80
  "default": "./dist/ui/css.css"
@@ -80,7 +84,8 @@
80
84
  }
81
85
  },
82
86
  "files": [
83
- "dist"
87
+ "dist",
88
+ "llms.txt"
84
89
  ],
85
90
  "publishConfig": {
86
91
  "access": "public"
@@ -91,7 +96,7 @@
91
96
  "dev": "tsdown --watch",
92
97
  "test": "vitest",
93
98
  "test:node": "node --run test",
94
- "test:ci": "vitest run",
99
+ "test:ci": "vitest run --passWithNoTests",
95
100
  "typecheck": "tsc --noEmit",
96
101
  "test:types": "tsc --noEmit",
97
102
  "lint": "eslint .",
@@ -99,19 +104,21 @@
99
104
  "release": "bun run build && bumpp --tag 'auth-v%s' && bun publish --tag latest"
100
105
  },
101
106
  "devDependencies": {
102
- "msw": "2.6.8"
107
+ "@neondatabase/internal": "0.0.1",
108
+ "msw": "2.6.8",
109
+ "next": "16.0.6"
103
110
  },
104
111
  "dependencies": {
112
+ "@neondatabase/auth-ui": "0.1.0-alpha.11",
105
113
  "@supabase/auth-js": "2.79.0",
106
114
  "better-auth": "1.4.6",
107
- "zod": "4.1.12",
108
115
  "jose": "6.1.2",
109
- "@neondatabase/auth-ui": "0.1.0-alpha.6"
116
+ "zod": "4.1.12"
110
117
  },
111
118
  "peerDependencies": {
112
119
  "react": ">=18.0.0",
113
120
  "react-dom": ">=18.0.0",
114
- "next": "^16.0.6"
121
+ "next": ">=16.0.6"
115
122
  },
116
123
  "peerDependenciesMeta": {
117
124
  "react": {