mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-08 12:27:44 +00:00
feat: add onError and throw error options for APIError (#162)
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
import { betterAuth } from "better-auth";
|
||||
import { prismaAdapter } from "better-auth/adapters/prisma";
|
||||
import { APIError } from "better-auth/api";
|
||||
import { twoFactor } from "better-auth/plugins";
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: prismaAdapter(
|
||||
{},
|
||||
{
|
||||
provider: "mysql",
|
||||
},
|
||||
),
|
||||
plugins: [twoFactor()],
|
||||
});
|
||||
|
||||
try {
|
||||
await auth.api.signOut();
|
||||
} catch (e) {
|
||||
if (e instanceof APIError) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { betterAuth } from "better-auth";
|
||||
import { prismaAdapter } from "better-auth/adapters/prisma";
|
||||
import { twoFactor } from "better-auth/plugins";
|
||||
|
||||
export const auth = betterAuth({
|
||||
baseURL: "http://localhost:4000",
|
||||
database: prismaAdapter(
|
||||
{},
|
||||
{
|
||||
provider: "sqlite",
|
||||
},
|
||||
),
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
},
|
||||
plugins: [twoFactor()],
|
||||
});
|
||||
|
||||
15
dev/bun/client.ts
Normal file
15
dev/bun/client.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createAuthClient } from "better-auth/client";
|
||||
|
||||
await fetch("http://localhost:4000/api/auth/sign-up/email", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
email: "test-2@test.com",
|
||||
password: "password",
|
||||
name: "test-2",
|
||||
}),
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => console.log(data));
|
||||
@@ -1,8 +1,7 @@
|
||||
import { auth } from "./_auth";
|
||||
import { auth } from "./auth";
|
||||
|
||||
Bun.serve({
|
||||
fetch(request, server) {
|
||||
auth;
|
||||
return new Response("Hello, World!");
|
||||
},
|
||||
fetch: auth.handler,
|
||||
port: 4000,
|
||||
});
|
||||
console.log("Server running on port 4000");
|
||||
|
||||
@@ -644,8 +644,8 @@ export const contents: Content[] = [
|
||||
icon: () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
width="1.2em"
|
||||
height="1.2em"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g
|
||||
|
||||
@@ -3,11 +3,11 @@ title: API
|
||||
description: Better Auth API
|
||||
---
|
||||
|
||||
When you create a new Better Auth instance, it gives you an `api` object. This object provides functions to interact with the server while your code is running server-side.
|
||||
When you create a new Better Auth instance, it gives you an `api` object. This object provides functions to interact with the server while your code is running server-side. You can use these functions to call any API endpoint on the server.
|
||||
|
||||
Any endpoint added to Better Auth, whether from plugins or the core, will be accessible through the `api` object.
|
||||
|
||||
## Calling API on the Server
|
||||
## Calling API Endpoints on the Server
|
||||
|
||||
To call an API endpoint on the server, import your `auth` instance and call the endpoint using the `api` object.
|
||||
|
||||
@@ -16,9 +16,7 @@ import { betterAuth } from "better-auth";
|
||||
import { headers } from "next/server";
|
||||
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
// add your plugins here
|
||||
]
|
||||
//...
|
||||
})
|
||||
|
||||
// calling get session on the server
|
||||
@@ -29,8 +27,18 @@ await auth.api.getSession({
|
||||
|
||||
Unlike the client, the server needs the values to be passed as an object with the key `body` for the body, `headers` for the headers, and `query` for the query.
|
||||
|
||||
|
||||
```ts title="server.ts"
|
||||
await auth.api.signInEmail({
|
||||
body: {
|
||||
email: "",
|
||||
password: ""
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
<Callout>
|
||||
Better Auth uses a library called [better-call](https://github.com/bekacru/better-call) to create API endpoints. Developed by the same team, it's built to integrate seamlessly with Better Auth. With Better Call, you can invoke `rest` API handlers as if they were regular functions.
|
||||
Better auth API endpoints are built on top of [better-call](https://github.com/bekacru/better-call), a tiny web framework that lets you call REST API endpoints as if they were regular functions and allows us to easily infer client types from the server.
|
||||
</Callout>
|
||||
|
||||
### Getting the `Response` Object
|
||||
@@ -47,7 +55,7 @@ const response = await auth.api.signInEmail({
|
||||
})
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
### Error Handling
|
||||
|
||||
When you call an API endpoint in the server, it will throw an error if the request fails. You can catch the error and handle it as you see fit. The error instance is an instance of `APIError`.
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
title: Secondary Storage
|
||||
description: Using secondary storage with BetterAuth
|
||||
---
|
||||
|
||||
@@ -250,6 +250,23 @@ list of trusted origins. This will disable CSRF token check for the provided ori
|
||||
/>
|
||||
|
||||
|
||||
### `onAPIError`
|
||||
|
||||
`OnAPIErrorOptions` - Options for handling API errors.
|
||||
|
||||
<TypeTable
|
||||
type={{
|
||||
throw: {
|
||||
description: "Throw the error.",
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
onError: {
|
||||
description: "Custom error handler.",
|
||||
type: '(error: Error, ctx: APIContext) => void'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
### `logger`
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"scripts": {
|
||||
"build": "turbo --filter \"./packages/*\" build",
|
||||
"dev": "turbo --filter \"./packages/*\" dev",
|
||||
"dev:dts": "turbo --filter \"./packages/*\" dev:dts",
|
||||
"clean": "turbo --filter \"./packages/*\" clean && rm -rf node_modules",
|
||||
"format": "biome format . --write",
|
||||
"lint": "biome check .",
|
||||
|
||||
@@ -219,6 +219,14 @@ export const router = <C extends AuthContext, Option extends BetterAuthOptions>(
|
||||
return res;
|
||||
},
|
||||
onError(e) {
|
||||
if (options.onAPIError?.throw) {
|
||||
throw e;
|
||||
}
|
||||
if (options.onAPIError?.onError) {
|
||||
options.onAPIError.onError(e, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
const log = options.logger?.verboseLogging ? logger : undefined;
|
||||
if (options.logger?.disabled !== true) {
|
||||
if (e instanceof APIError) {
|
||||
@@ -230,7 +238,7 @@ export const router = <C extends AuthContext, Option extends BetterAuthOptions>(
|
||||
if (typeof e === "object" && e !== null && "message" in e) {
|
||||
const errorMessage = e.message as string;
|
||||
if (!errorMessage || typeof errorMessage !== "string") {
|
||||
log?.error(e);
|
||||
logger?.error(e);
|
||||
return;
|
||||
}
|
||||
if (errorMessage.includes("no such table")) {
|
||||
@@ -258,10 +266,10 @@ export const router = <C extends AuthContext, Option extends BetterAuthOptions>(
|
||||
)} to create the tables. There are missing tables in your MySQL database.`,
|
||||
);
|
||||
} else {
|
||||
log?.error(e);
|
||||
logger?.error(e);
|
||||
}
|
||||
} else {
|
||||
log?.error(e);
|
||||
logger?.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { BetterSqlite3Database, MysqlPool } from "./database";
|
||||
import type { KyselyDatabaseType } from "../adapters/kysely-adapter/types";
|
||||
import type { FieldAttribute } from "../db";
|
||||
import type { RateLimit } from "./models";
|
||||
import type { EligibleCookies } from "../cookies";
|
||||
import type { AuthContext } from ".";
|
||||
|
||||
export interface BetterAuthOptions {
|
||||
/**
|
||||
@@ -436,4 +436,22 @@ export interface BetterAuthOptions {
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* API error handling
|
||||
*/
|
||||
onAPIError?: {
|
||||
/**
|
||||
* Throw an error on API error
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
throw?: boolean;
|
||||
/**
|
||||
* Custom error handler
|
||||
*
|
||||
* @param error
|
||||
* @param ctx - Auth context
|
||||
*/
|
||||
onError?: (error: unknown, ctx: AuthContext) => void | Promise<void>;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user