@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
package/README.md CHANGED
@@ -269,19 +269,34 @@ See the [Next.js Setup Guide](./NEXT-JS.md) for comprehensive documentation incl
269
269
 
270
270
  ## UI Components
271
271
 
272
- Pre-built login forms and auth pages are included. No extra installation needed.
272
+ Pre-built login forms and auth pages live in `@neondatabase/auth-ui`. The
273
+ legacy `@neondatabase/auth/react/ui` and `@neondatabase/auth/ui/*` entrypoints
274
+ still work for compatibility, but they are deprecated and will be removed in
275
+ the next major version.
276
+
277
+ To migrate existing imports, run:
278
+
279
+ ```bash
280
+ npx -p @neondatabase/auth neon-auth-codemod --write <path>
281
+ ```
273
282
 
274
283
  ### 1. Import CSS
275
284
 
285
+ Install the UI package alongside `@neondatabase/auth`:
286
+
287
+ ```bash
288
+ npm install @neondatabase/auth-ui
289
+ ```
290
+
276
291
  **Without Tailwind CSS:**
277
292
  ```typescript
278
- import '@neondatabase/auth/ui/css';
293
+ import '@neondatabase/auth-ui/css';
279
294
  ```
280
295
 
281
296
  **With Tailwind CSS v4:**
282
297
  ```css
283
298
  @import 'tailwindcss';
284
- @import '@neondatabase/auth/ui/tailwind';
299
+ @import '@neondatabase/auth-ui/tailwind';
285
300
  ```
286
301
 
287
302
  ### 2. Setup Provider
@@ -289,9 +304,9 @@ import '@neondatabase/auth/ui/css';
289
304
  ```typescript
290
305
  "use client"
291
306
 
292
- import { NeonAuthUIProvider } from "@neondatabase/auth/react/ui"
307
+ import { NeonAuthUIProvider } from "@neondatabase/auth-ui"
293
308
  import { createAuthClient } from "@neondatabase/auth"
294
- import "@neondatabase/auth/ui/css"
309
+ import "@neondatabase/auth-ui/css"
295
310
 
296
311
  const authClient = createAuthClient('https://your-auth-url.com')
297
312
 
@@ -311,7 +326,7 @@ export function AuthProvider({ children }) {
311
326
  Use `AuthView` to render complete auth flows based on the URL path:
312
327
 
313
328
  ```typescript
314
- import { AuthView } from "@neondatabase/auth/react/ui"
329
+ import { AuthView } from "@neondatabase/auth-ui"
315
330
 
316
331
  // Renders sign-in, sign-up, forgot-password, etc. based on path
317
332
  <AuthView path="sign-in" />
@@ -320,7 +335,7 @@ import { AuthView } from "@neondatabase/auth/react/ui"
320
335
  **Option B: Individual Components**
321
336
 
322
337
  ```typescript
323
- import { SignInForm, UserButton } from "@neondatabase/auth/react/ui"
338
+ import { SignInForm, UserButton } from "@neondatabase/auth-ui"
324
339
 
325
340
  <SignInForm />
326
341
  <UserButton />
@@ -0,0 +1,439 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable no-undef */
3
+ import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
4
+ // eslint-disable-next-line unicorn/import-style
5
+ import { dirname, extname, join, resolve } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const replacements = [
9
+ ['@neondatabase/auth/react/ui/server', '@neondatabase/auth-ui/server'],
10
+ ['@neondatabase/auth/react/ui', '@neondatabase/auth-ui'],
11
+ ['@neondatabase/auth/ui/css', '@neondatabase/auth-ui/css'],
12
+ ['@neondatabase/auth/ui/tailwind', '@neondatabase/auth-ui/tailwind'],
13
+ ['@neondatabase/neon-js/auth/react/ui/server', '@neondatabase/auth-ui/server'],
14
+ ['@neondatabase/neon-js/auth/react/ui', '@neondatabase/auth-ui'],
15
+ ['@neondatabase/neon-js/ui/css', '@neondatabase/auth-ui/css'],
16
+ ['@neondatabase/neon-js/ui/tailwind', '@neondatabase/auth-ui/tailwind'],
17
+ ];
18
+
19
+ const compatibilityReactSources = new Set([
20
+ '@neondatabase/auth/react',
21
+ '@neondatabase/neon-js/auth/react',
22
+ ]);
23
+
24
+ const authUiExports = new Set([
25
+ 'AcceptInvitationCard',
26
+ 'AccountSettingsCards',
27
+ 'AccountView',
28
+ 'AccountsCard',
29
+ 'AppleIcon',
30
+ 'AuthCallback',
31
+ 'AuthForm',
32
+ 'AuthLoading',
33
+ 'AuthUIContext',
34
+ 'AuthUIProvider',
35
+ 'AuthView',
36
+ 'ChangeEmailCard',
37
+ 'ChangePasswordCard',
38
+ 'CreateOrganizationDialog',
39
+ 'CreateTeamDialog',
40
+ 'DeleteAccountCard',
41
+ 'DeleteOrganizationCard',
42
+ 'DiscordIcon',
43
+ 'DropboxIcon',
44
+ 'FacebookIcon',
45
+ 'ForgotPasswordForm',
46
+ 'GitHubIcon',
47
+ 'GitLabIcon',
48
+ 'GoogleIcon',
49
+ 'HuggingFaceIcon',
50
+ 'InputFieldSkeleton',
51
+ 'KickIcon',
52
+ 'LinearIcon',
53
+ 'LinkedInIcon',
54
+ 'MagicLinkForm',
55
+ 'MicrosoftIcon',
56
+ 'NeonAuthUIProvider',
57
+ 'NotionIcon',
58
+ 'OrganizationCellView',
59
+ 'OrganizationInvitationsCard',
60
+ 'OrganizationLogo',
61
+ 'OrganizationLogoCard',
62
+ 'OrganizationMembersCard',
63
+ 'OrganizationNameCard',
64
+ 'OrganizationSettingsCards',
65
+ 'OrganizationSlugCard',
66
+ 'OrganizationSwitcher',
67
+ 'OrganizationView',
68
+ 'OrganizationsCard',
69
+ 'PasskeysCard',
70
+ 'PasswordInput',
71
+ 'ProvidersCard',
72
+ 'RecoverAccountForm',
73
+ 'RedditIcon',
74
+ 'RedirectToSignIn',
75
+ 'RedirectToSignUp',
76
+ 'ResetPasswordForm',
77
+ 'RobloxIcon',
78
+ 'SecuritySettingsCards',
79
+ 'SessionsCard',
80
+ 'SettingsCard',
81
+ 'SettingsCellSkeleton',
82
+ 'SignInForm',
83
+ 'SignOut',
84
+ 'SignUpForm',
85
+ 'SignedIn',
86
+ 'SignedOut',
87
+ 'SlackIcon',
88
+ 'TeamCell',
89
+ 'TeamsCard',
90
+ 'SpotifyIcon',
91
+ 'TikTokIcon',
92
+ 'TwoFactorCard',
93
+ 'TwoFactorForm',
94
+ 'TwitchIcon',
95
+ 'UpdateAvatarCard',
96
+ 'UpdateFieldCard',
97
+ 'UpdateNameCard',
98
+ 'UpdateUsernameCard',
99
+ 'UserAvatar',
100
+ 'UserButton',
101
+ 'UserInvitationsCard',
102
+ 'UserView',
103
+ 'VKIcon',
104
+ 'XIcon',
105
+ 'ZoomIcon',
106
+ 'accountViewPaths',
107
+ 'authLocalization',
108
+ 'authViewPaths',
109
+ 'getViewByPath',
110
+ 'organizationViewPaths',
111
+ 'socialProviders',
112
+ 'useAuthData',
113
+ 'useAuthenticate',
114
+ 'useCurrentOrganization',
115
+ 'useTheme',
116
+ ]);
117
+
118
+ const supportedExtensions = new Set([
119
+ '.cjs',
120
+ '.css',
121
+ '.js',
122
+ '.jsx',
123
+ '.md',
124
+ '.mdx',
125
+ '.mjs',
126
+ '.scss',
127
+ '.ts',
128
+ '.tsx',
129
+ ]);
130
+
131
+ const ignoredDirectories = new Set([
132
+ '.git',
133
+ '.next',
134
+ 'build',
135
+ 'coverage',
136
+ 'dist',
137
+ 'node_modules',
138
+ ]);
139
+
140
+ function parseArgs(argv) {
141
+ const options = {
142
+ check: false,
143
+ write: false,
144
+ verifyExports: false,
145
+ dependencyVersion: undefined,
146
+ targets: [],
147
+ };
148
+
149
+ for (const arg of argv) {
150
+ switch (arg) {
151
+ case '--check': {
152
+ options.check = true;
153
+
154
+ break;
155
+ }
156
+ case '--write': {
157
+ options.write = true;
158
+
159
+ break;
160
+ }
161
+ case '--verify-exports': {
162
+ options.verifyExports = true;
163
+
164
+ break;
165
+ }
166
+ default: { if (arg.startsWith('--dependency-version=')) {
167
+ options.dependencyVersion = arg.slice('--dependency-version='.length);
168
+ } else if (arg === '--help' || arg === '-h') {
169
+ printHelp();
170
+ process.exit(0);
171
+ } else {
172
+ options.targets.push(arg);
173
+ }
174
+ }
175
+ }
176
+ }
177
+
178
+ if (options.verifyExports) {
179
+ return options;
180
+ }
181
+
182
+ if (options.check === options.write) {
183
+ throw new Error('Choose exactly one mode: --check or --write.');
184
+ }
185
+
186
+ if (options.targets.length === 0) {
187
+ options.targets.push('.');
188
+ }
189
+
190
+ options.dependencyVersion ??= getDefaultAuthUiDependencyVersion();
191
+
192
+ return options;
193
+ }
194
+
195
+ function printHelp() {
196
+ console.log(`Usage: neon-auth-codemod (--check|--write|--verify-exports) [paths...]
197
+
198
+ Migrates deprecated Neon Auth UI compatibility imports to @neondatabase/auth-ui.
199
+
200
+ Options:
201
+ --check Report files that need migration and exit non-zero.
202
+ --write Rewrite files in place and update nearest package.json files.
203
+ --verify-exports Check codemod UI symbol list against packages/auth/src/react/ui/index.ts.
204
+ --dependency-version=<version> Version added to package.json dependencies. Defaults to this package's @neondatabase/auth-ui dependency.
205
+ `);
206
+ }
207
+
208
+ function getDefaultAuthUiDependencyVersion() {
209
+ const currentFile = fileURLToPath(import.meta.url);
210
+ const packageJsonPath = resolve(dirname(currentFile), '..', 'package.json');
211
+
212
+ try {
213
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
214
+ const version = packageJson.dependencies?.['@neondatabase/auth-ui'];
215
+ if (typeof version === 'string' && !version.startsWith('workspace:')) {
216
+ return version;
217
+ }
218
+ } catch {
219
+ // Fall through to the stable default below.
220
+ }
221
+
222
+ return '^0.1.0';
223
+ }
224
+
225
+ function* walk(path) {
226
+ if (!existsSync(path)) {
227
+ return;
228
+ }
229
+
230
+ const stat = statSync(path);
231
+ if (stat.isFile()) {
232
+ if (supportedExtensions.has(extname(path))) {
233
+ yield path;
234
+ }
235
+ return;
236
+ }
237
+
238
+ if (!stat.isDirectory()) {
239
+ return;
240
+ }
241
+
242
+ for (const entry of readdirSync(path)) {
243
+ if (ignoredDirectories.has(entry)) {
244
+ continue;
245
+ }
246
+ yield* walk(join(path, entry));
247
+ }
248
+ }
249
+
250
+ function rewriteText(text) {
251
+ let next = rewriteCompatibilityReactImports(text);
252
+ for (const [from, to] of replacements) {
253
+ next = next.split(from).join(to);
254
+ }
255
+ return next;
256
+ }
257
+
258
+ function rewriteCompatibilityReactImports(text) {
259
+ return text.replaceAll(
260
+ /import\s+(type\s+)?\{([^}]*)\}\s+from\s+(['"])(@neondatabase\/(?:auth\/react|neon-js\/auth\/react))\3;?/g,
261
+ (match, typeKeyword = '', specifierBlock, quote, source) => {
262
+ if (!compatibilityReactSources.has(source)) {
263
+ return match;
264
+ }
265
+
266
+ const specifiers = specifierBlock
267
+ .split(',')
268
+ .map((specifier) => specifier.trim())
269
+ .filter(Boolean);
270
+ const uiSpecifiers = [];
271
+ const remainingSpecifiers = [];
272
+
273
+ for (const specifier of specifiers) {
274
+ const importedName = specifier.split(/\s+as\s+/i)[0]?.replace(/^type\s+/, '').trim();
275
+ if (authUiExports.has(importedName)) {
276
+ uiSpecifiers.push(specifier);
277
+ } else {
278
+ remainingSpecifiers.push(specifier);
279
+ }
280
+ }
281
+
282
+ if (uiSpecifiers.length === 0) {
283
+ return match;
284
+ }
285
+
286
+ const statements = [
287
+ `import ${typeKeyword}{ ${uiSpecifiers.join(', ')} } from '@neondatabase/auth-ui';`,
288
+ ];
289
+
290
+ if (remainingSpecifiers.length > 0) {
291
+ statements.push(
292
+ `import ${typeKeyword}{ ${remainingSpecifiers.join(', ')} } from ${quote}${source}${quote};`
293
+ );
294
+ }
295
+
296
+ return statements.join('\n');
297
+ }
298
+ );
299
+ }
300
+
301
+ export function extractAuthUiValueExports(sourcePath) {
302
+ const source = readFileSync(sourcePath, 'utf8');
303
+ const exports = new Set();
304
+
305
+ for (const match of source.matchAll(/export\s+\{([^}]*)\}\s+from\s+['"]@neondatabase\/auth-ui['"]/g)) {
306
+ for (const specifier of match[1].split(',')) {
307
+ const name = specifier.trim().split(/\s+as\s+/i)[0]?.trim();
308
+ if (name) {
309
+ exports.add(name);
310
+ }
311
+ }
312
+ }
313
+
314
+ return exports;
315
+ }
316
+
317
+ export function findMissingAuthUiExports(sourcePath = resolve('packages/auth/src/react/ui/index.ts')) {
318
+ const sourceExports = extractAuthUiValueExports(sourcePath);
319
+ return [...sourceExports].filter((name) => !authUiExports.has(name)).toSorted();
320
+ }
321
+
322
+ export function verifyAuthUiExports() {
323
+ const sourcePath = resolve('packages/auth/src/react/ui/index.ts');
324
+ const sourceExports = extractAuthUiValueExports(sourcePath);
325
+ const missing = findMissingAuthUiExports(sourcePath);
326
+
327
+ if (missing.length > 0) {
328
+ console.error(
329
+ `authUiExports is missing ${missing.length} value export(s) from ${sourcePath}:`
330
+ );
331
+ for (const name of missing) {
332
+ console.error(`- ${name}`);
333
+ }
334
+ process.exitCode = 1;
335
+ return;
336
+ }
337
+
338
+ console.log(`authUiExports covers ${sourceExports.size} value export(s) from ${sourcePath}.`);
339
+ }
340
+
341
+ function findPackageJson(start) {
342
+ let current = resolve(statSync(start).isDirectory() ? start : join(start, '..'));
343
+ const root = resolve('/');
344
+
345
+ while (current !== root) {
346
+ const candidate = join(current, 'package.json');
347
+ if (existsSync(candidate)) {
348
+ return candidate;
349
+ }
350
+ current = resolve(current, '..');
351
+ }
352
+
353
+ return null;
354
+ }
355
+
356
+ function updatePackageJson(packageJsonPath, dependencyVersion) {
357
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
358
+ packageJson.dependencies ??= {};
359
+
360
+ if (packageJson.dependencies['@neondatabase/auth-ui']) {
361
+ return false;
362
+ }
363
+
364
+ packageJson.dependencies['@neondatabase/auth-ui'] = dependencyVersion;
365
+ writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
366
+ return true;
367
+ }
368
+
369
+ function main() {
370
+ const options = parseArgs(process.argv.slice(2));
371
+ if (options.verifyExports) {
372
+ verifyAuthUiExports();
373
+ return;
374
+ }
375
+
376
+ const changedFiles = [];
377
+ const packageJsons = new Set();
378
+
379
+ for (const target of options.targets.map((target) => resolve(target))) {
380
+ for (const file of walk(target)) {
381
+ const original = readFileSync(file, 'utf8');
382
+ const next = rewriteText(original);
383
+ if (next === original) {
384
+ continue;
385
+ }
386
+
387
+ changedFiles.push(file);
388
+ const packageJsonPath = findPackageJson(file);
389
+ if (packageJsonPath) {
390
+ packageJsons.add(packageJsonPath);
391
+ }
392
+
393
+ if (options.write) {
394
+ writeFileSync(file, next);
395
+ }
396
+ }
397
+ }
398
+
399
+ const changedPackageJsons = [];
400
+ if (options.write) {
401
+ for (const packageJsonPath of packageJsons) {
402
+ if (updatePackageJson(packageJsonPath, options.dependencyVersion)) {
403
+ changedPackageJsons.push(packageJsonPath);
404
+ }
405
+ }
406
+ }
407
+
408
+ if (changedFiles.length === 0) {
409
+ console.log('No deprecated Neon Auth UI imports found.');
410
+ return;
411
+ }
412
+
413
+ const mode = options.write ? 'Updated' : 'Would update';
414
+ console.log(`${mode} ${changedFiles.length} file(s):`);
415
+ for (const file of changedFiles) {
416
+ console.log(`- ${file}`);
417
+ }
418
+
419
+ if (changedPackageJsons.length > 0) {
420
+ console.log(`\nAdded @neondatabase/auth-ui to ${changedPackageJsons.length} package.json file(s):`);
421
+ for (const packageJsonPath of changedPackageJsons) {
422
+ console.log(`- ${packageJsonPath}`);
423
+ }
424
+ console.log('\nRun your package manager install command to update the lockfile.');
425
+ }
426
+
427
+ if (options.check) {
428
+ process.exitCode = 1;
429
+ }
430
+ }
431
+
432
+ if (import.meta.url === `file://${process.argv[1]}`) {
433
+ try {
434
+ main();
435
+ } catch (error) {
436
+ console.error(error instanceof Error ? error.message : String(error));
437
+ process.exitCode = 1;
438
+ }
439
+ }
@@ -1,6 +1,6 @@
1
- import { a as NEON_AUTH_POPUP_PARAM_NAME, c as SESSION_CACHE_TTL_MS, i as NEON_AUTH_POPUP_CALLBACK_ROUTE, o as NEON_AUTH_SESSION_VERIFIER_PARAM_NAME, r as NEON_AUTH_POPUP_CALLBACK_PARAM_NAME, s as OAUTH_POPUP_MESSAGE_TYPE, t as CLOCK_SKEW_BUFFER_MS } from "./constants-Cupc_bln.mjs";
1
+ import { d as NEON_AUTH_POPUP_CALLBACK_PARAM_NAME, f as NEON_AUTH_POPUP_CALLBACK_ROUTE, g as SESSION_CACHE_TTL_MS, h as OAUTH_POPUP_MESSAGE_TYPE, m as NEON_AUTH_SESSION_VERIFIER_PARAM_NAME, p as NEON_AUTH_POPUP_PARAM_NAME, r as normalizeBetterAuthError, u as CLOCK_SKEW_BUFFER_MS } from "./better-auth-helpers-Bkezghej.mjs";
2
2
  import { getGlobalBroadcastChannel } from "better-auth/client";
3
- import { adminClient, emailOTPClient, jwtClient, organizationClient } from "better-auth/client/plugins";
3
+ import { adminClient, emailOTPClient, jwtClient, magicLinkClient, organizationClient } from "better-auth/client/plugins";
4
4
  import z from "zod";
5
5
 
6
6
  //#region src/core/in-flight-request-manager.ts
@@ -490,6 +490,9 @@ const BETTER_AUTH_METHODS_HOOKS = {
490
490
  },
491
491
  getSession: {
492
492
  beforeFetch: () => {
493
+ if (isBrowser()) {
494
+ if (new URLSearchParams(globalThis.window.location.search).has(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME)) return null;
495
+ }
493
496
  const cachedData = BETTER_AUTH_METHODS_CACHE.getCachedSession();
494
497
  if (!cachedData) return null;
495
498
  return Response.json(cachedData, { status: 200 });
@@ -629,7 +632,7 @@ function initBroadcastChannel() {
629
632
  //#endregion
630
633
  //#region package.json
631
634
  var name = "@neondatabase/auth";
632
- var version = "0.3.0-beta";
635
+ var version = "0.4.1-beta";
633
636
 
634
637
  //#endregion
635
638
  //#region ../internal/dist/index.mjs
@@ -724,6 +727,7 @@ const supportedBetterAuthClientPlugins = [
724
727
  adminClient(),
725
728
  organizationClient(),
726
729
  emailOTPClient(),
730
+ magicLinkClient(),
727
731
  anonymousTokenClient()
728
732
  ];
729
733
  var NeonAuthAdapterCore = class {
@@ -757,10 +761,13 @@ var NeonAuthAdapterCore = class {
757
761
  });
758
762
  if (!response$1.ok) {
759
763
  const body = await response$1.clone().json().catch(() => ({}));
760
- const err = new Error(body.message || `HTTP ${response$1.status} ${response$1.statusText}`);
761
- err.status = response$1.status;
762
- err.statusText = response$1.statusText;
763
- throw err;
764
+ throw normalizeBetterAuthError({
765
+ status: response$1.status,
766
+ statusText: response$1.statusText,
767
+ message: body.message || `HTTP ${response$1.status} ${response$1.statusText}`,
768
+ code: body.code,
769
+ body
770
+ });
764
771
  }
765
772
  return response$1;
766
773
  }
@@ -776,10 +783,13 @@ var NeonAuthAdapterCore = class {
776
783
  }));
777
784
  if (!response.ok) {
778
785
  const errorBody = await response.clone().json().catch(() => ({}));
779
- const err = new Error(errorBody.message || `HTTP ${response.status} ${response.statusText}`);
780
- err.status = response.status;
781
- err.statusText = response.statusText;
782
- throw err;
786
+ throw normalizeBetterAuthError({
787
+ status: response.status,
788
+ statusText: response.statusText,
789
+ message: errorBody.message || `HTTP ${response.status} ${response.statusText}`,
790
+ code: errorBody.code,
791
+ body: errorBody
792
+ });
783
793
  }
784
794
  return response.clone();
785
795
  },