fix: remove db falt config (#57)

* remove db object config

* change docs
This commit is contained in:
Bereket Engida
2024-10-01 17:18:53 +03:00
committed by GitHub
parent 9fdffd2d3f
commit d239682767
51 changed files with 264 additions and 589 deletions

View File

@@ -6,7 +6,9 @@
},
"dependencies": {
"@hono/node-server": "^1.12.2",
"better-auth": "^0.0.4",
"better-auth": "workspace:*",
"@types/better-sqlite3": "^7.6.11",
"better-sqlite3": "^11.3.0",
"dotenv": "^16.4.5",
"hono": "^4.5.9",
"tsx": "^4.19.0"

View File

@@ -1,20 +1,17 @@
import Database from "better-sqlite3";
import { betterAuth } from "better-auth";
import { organization, twoFactor, username } from "better-auth/plugins";
import { github } from "better-auth/social-providers";
export const auth = betterAuth({
baseURL: "http://localhost:3000",
basePath: "/auth",
database: {
provider: "sqlite",
url: "./db.sqlite",
database: new Database("./db.sqlite"),
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID || "",
clientSecret: process.env.GITHUB_CLIENT_SECRET || "",
},
},
socialProviders: [
github({
clientId: process.env.GITHUB_CLIENT_ID as string,
clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
}),
],
plugins: [
twoFactor({
issuer: "BetterAuth",

View File

@@ -14,6 +14,7 @@
"dependencies": {
"@noble/ciphers": "^0.6.0",
"better-auth": "workspace:*",
"@types/better-sqlite3": "^7.6.11",
"better-sqlite3": "^11.3.0",
"oslo": "^1.2.1",
"pg": "^8.13.0"

View File

@@ -8,7 +8,9 @@
"@types/express": "^4.17.21"
},
"peerDependencies": {
"typescript": "^5.0.0"
"typescript": "^5.0.0",
"@types/better-sqlite3": "^7.6.11",
"better-sqlite3": "^11.3.0"
},
"dependencies": {
"better-auth": "workspace:*",

View File

@@ -29,10 +29,6 @@ description: Apple
import { apple } from "better-auth/social-providers"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
socialProviders: { // [!code highlight]
apple({ // [!code highlight]
clientId: process.env.APPLE_CLIENT_ID as string, // [!code highlight]

View File

@@ -20,10 +20,6 @@ description: Discord Provider
import { discord } from "better-auth/social-providers"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
socialProviders: { // [!code highlight]
discord: { // [!code highlight]
clientId: process.env.DISCORD_CLIENT_ID as string, // [!code highlight]

View File

@@ -17,10 +17,6 @@ To enable email and password authentication, you need to set the `emailAndPasswo
import { betterAuth } from "better-auth"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
emailAndPassword: { // [!code highlight]
enabled: true // [!code highlight]
} // [!code highlight]
@@ -116,10 +112,6 @@ to allow users to reset a password first you need to provider `sendResetPassword
import { betterAuth } from "better-auth"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
emailAndPassword: { // [!code highlight]
enabled: true, // [!code highlight]
async sendResetPassword(url, user) { // [!code highlight]

View File

@@ -20,10 +20,6 @@ description: Facebook Provider
import { facebook } from "better-auth/social-providers"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
socialProviders: { // [!code highlight]
facebook: { // [!code highlight]
clientId: process.env.FACEBOOK_CLIENT_ID as string, // [!code highlight]

View File

@@ -20,10 +20,6 @@ description: Github Provider
import { github } from "better-auth/social-providers"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
socialProviders: { // [!code highlight]
github: { // [!code highlight]
clientId: process.env.GITHUB_CLIENT_ID as string, // [!code highlight]

View File

@@ -20,10 +20,6 @@ description: Google Provider
import { google } from "better-auth/social-providers"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
socialProviders: { // [!code highlight]
google: { // [!code highlight]
clientId: process.env.GOOGLE_CLIENT_ID as string, // [!code highlight]

View File

@@ -20,10 +20,7 @@ description: Spotify Provider
import { spotify } from "better-auth/social-providers"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
socialProviders: { // [!code highlight]
spotify: { // [!code highlight]
clientId: process.env.SPOTIFY_CLIENT_ID as string, // [!code highlight]

View File

@@ -20,10 +20,6 @@ description: Twitch Provider
import { twitch } from "better-auth/social-providers"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
socialProviders: { // [!code highlight]
twitch: { // [!code highlight]
clientId: process.env.TWITCH_CLIENT_ID as string, // [!code highlight]

View File

@@ -20,10 +20,6 @@ description: Twitter Provider
import { twitter } from "better-auth/social-providers"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
socialProviders: {// [!code highlight]
twitter: { // [!code highlight]
clientId: process.env.TWITTER_CLIENT_ID, // [!code highlight]

View File

@@ -15,10 +15,6 @@ Better auth uses a library called [better-call](https://github.com/bekacru/bette
import { betterAuth } from "better-auth";
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
// add your plugins here
]

View File

@@ -12,33 +12,37 @@ You can also pass a kysley dialect directly to use other databases supported by
**Example: Sqlite**
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import Database from "better-sqlite3"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "path/to/database.sqlite"
}
database: new Database("database.sqlite")
})
```
**Example: Postgres**
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { Pool } from "pg"
export const auth = await betterAuth({
database: {
provider: "postgres",
url: "postgres://user:password@localhost:5432/database"
}
database: new Pool({
connectionString: "postgres://user:password@localhost:5432/database"
})
})
```
**Exmaple: Mysql**
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { createPool } from "mysql2/promise"
export const auth = await betterAuth({
database: {
provider: "mysql",
url: "mysql://user:password@localhost:3306/database"
}
database: createPool({
host: "localhost",
user: "root",
password: "password",
database: "database"
})
})
```

View File

@@ -17,10 +17,6 @@ To add a plugin on the server, include it in the `plugins` array in your auth co
import { betterAuth } from "better-auth";
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
// Add your plugins here
]

View File

@@ -23,12 +23,10 @@ You can also infer types on the server side.
```ts title="auth.ts" twoslash
import { betterAuth } from "better-auth"
import Database from "better-sqlite3"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
}
database: new Database("database.db")
})
type Session = typeof auth.$Infer.Session

View File

@@ -1,5 +1,5 @@
---
title: Installtion
title: Installation
description: Learn how to configure Better Auth in your project.
---
@@ -69,16 +69,42 @@ export const auth = betterAuth({
Better Auth requires a database to store user data. By default, it uses [Kysely](https://kysely.dev/) for database connections and queries, with support for `postgresql`, `mysql`, and `sqlite` out of the box.
<Tabs items={["sqlite", "postgres", "mysql"]}>
<Tab value="sqlite">
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { betterAuth } from "better-auth";
import Database from "better-sqlite3";
export const auth = betterAuth({
database: {
provider: "sqlite", // or "mysql", "postgresql"
url: "./db.sqlite", // path to your database or connection string
}
database: new Database("./sqlite.db"),
})
```
</Tab>
<Tab value="postgres">
```ts title="auth.ts"
import { betterAuth } from "better-auth";
import { Pool } from "pg";
export const auth = betterAuth({
database: new Pool({
// connection options
})
})
```
</Tab>
<Tab value="mysql">
```ts title="auth.ts"
import { betterAuth } from "better-auth";
import { createPool } from "mysql2/promise";
export const auth = betterAuth({
database: createPool({
// connection options
})
})
```
</Tab>
</Tabs>
You can also use any dialect supported by Kysely in the database configuration.
@@ -96,6 +122,8 @@ export const auth = betterAuth({
});
```
We recommend using the built-in Kysely adapter for better performance if your database is supported.
**Adapters**
If your database isnt supported by Kysely, you can use an adapter to connect. Simply import the adapter and pass it into the `database` option.
@@ -178,10 +206,7 @@ import { betterAuth } from "better-auth"
import { github } from "better-auth/social-providers"
export const auth = betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
//...other options
emailAndPassword: { // [!code highlight]
enabled: true // [!code highlight]
},// [!code highlight]

View File

@@ -11,20 +11,7 @@ Before you start, make sure you have a better auth instance configured. If you h
We need to mount the handler to an API route. Create a route file inside `/api/[...auth]` directory. And add the following code:
```ts twoslash title="api/[...auth]/route.ts"
//@filename: @/lib/auth.ts
import { betterAuth } from "better-auth"
export const auth = betterAuth({
database: {
provider: "sqlite", //change this to your database provider
url: "./db.sqlite", // path to your database or connection string
}
// Refer to the api documentation for more configuration options
})
// ---cut---
//@filename: api/[...auth]/route.ts
//---cut---
```ts title="api/[...auth]/route.ts"
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
@@ -39,7 +26,7 @@ export const { GET, POST } = toNextJsHandler(auth.handler);
Create a client instance. You can name the file anything you want. Here we are creating `client.ts` file inside the `lib/` directory.
```ts twoslash title="client.ts"
```ts title="client.ts"
import { createAuthClient } from "better-auth/react" // make sure to import from better-auth/react
export const client = createAuthClient({
@@ -58,20 +45,7 @@ The `api` object exported from the auth instance contains all the actions that y
**Example: Getting Session on a server action**
```tsx twoslash title="server.ts"
//@filename: @/lib/auth.ts
import { betterAuth } from "better-auth"
export const auth = betterAuth({
database: {
provider: "sqlite", //change this to your database provider
url: "./db.sqlite", // path to your database or connection string
}
// Refer to the api documentation for more configuration options
})
// ---cut---
//@filename: server.ts
//---cut---
```tsx title="server.ts"
import { auth } from "@/lib/auth"
import { headers } from "next/headers"
@@ -109,7 +83,7 @@ export async function ServerComponent() {
You can use the `authMiddleware` to protect your routes. It's a wrapper around the Next.js middleware.
```ts twoslash title="middleware.ts"s
```ts title="middleware.ts"s
import { authMiddleware } from "better-auth/next-js"
export default authMiddleware({

View File

@@ -31,7 +31,7 @@ npx better-auth migrate
Create a client instance. You can name the file anything you want. Here we are creating `client.ts` file inside the `lib/` directory.
```ts twoslash title="client.ts"
```ts title="client.ts"
import { createAuthClient } from "better-auth/vue" // make sure to import from better-auth/vue
export const client = createAuthClient({

View File

@@ -29,7 +29,7 @@ npx better-auth migrate
Create a client instance. You can name the file anything you want. Here we are creating `client.ts` file inside the `lib/` directory.
```ts twoslash title="client.ts"
```ts title="client.ts"
import { createAuthClient } from "better-auth/svelte" // make sure to import from better-auth/svlete
export const client = createAuthClient({

View File

@@ -182,15 +182,11 @@ OTP (One-Time Password) is similar to TOTP but the code is sent directly to the
Before using OTP to verify the second factor, you need to configure `sendOTP` in your better auth instance. This function is responsible for sending the OTP to the user's email, phone, or any other method supported by your application.
```ts title="auth.ts" twoslash
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { twoFactor } from "better-auth/plugins"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
twoFactor({
otpOptions: {
@@ -362,7 +358,7 @@ backup codes are generated and stored in the database when the user enabled two
To use the two factor plugin in the client, you need to add it on your plugins list.
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { twoFactorClient } from "better-auth/client/plugins"

View File

@@ -7,15 +7,11 @@ The Bearer plugin allows you to authenticate with a Bearer token instead of a br
## Add the Bearer plugin
```ts title="auth.ts" twoslash
```ts title="auth.ts"
import { betterAuth } from "better-auth";
import { bearer } from "better-auth/plugins";
export const auth = betterAuth({
database: {
provider: 'sqlite',
url: './db.sqlite'
},
plugins: [bearer()]
});
```

View File

@@ -17,10 +17,6 @@ Magic link or email link is a way to authenticate users without a password. When
import { magicLink } from "better-auth/plugins";
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
magicLink({
sendMagicLink: async (data: {

View File

@@ -11,15 +11,11 @@ Organizations simplifies user access and permissions management. Assign roles an
<Steps>
<Step>
### Add the plugin to your **auth** config
```ts title="auth.ts" twoslash
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [ // [!code highlight]
organization() // [!code highlight]
] // [!code highlight]
@@ -44,7 +40,7 @@ export const auth = await betterAuth({
<Step>
### Add the client plugin
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"
@@ -72,7 +68,7 @@ To create an organization, you need to provide:
- `slug`: The slug of the organization.
- `logo`: The logo of the organization. (Optional)
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"

View File

@@ -22,15 +22,12 @@ The passkey plugin implementation is powered by [simple-web-authn](https://simpl
`origin`: The URL at which registrations and authentications should occur. 'http://localhost' and 'http://localhost:PORT' are also valid.Do NOT include any trailing /
```ts title="auth.ts" twoslash
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { passkey } from "better-auth/plugins"
export const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [ // [!code highlight]
passkey(), // [!code highlight]
], // [!code highlight]
@@ -53,7 +50,7 @@ The passkey plugin implementation is powered by [simple-web-authn](https://simpl
<Step>
### Add the client plugin
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { passkeyClient } from "better-auth/client/plugins"
@@ -73,7 +70,7 @@ The passkey plugin implementation is powered by [simple-web-authn](https://simpl
To add or register a passkey make sure a user is authenticated and then call the `passkey.addPasskey` function provided by the client.
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { passkeyClient } from "better-auth/client/plugins"
@@ -97,7 +94,7 @@ Signin method accepts:
`callbackURL`: The URL to redirect to after the user has signed in. (optional)
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { passkeyClient } from "better-auth/client/plugins"

View File

@@ -11,15 +11,11 @@ The username plugin wraps the email and password authenticator and adds username
<Step>
### Add Plugin to the server
```ts title="auth.ts" twoslash
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"
const auth = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [ // [!code highlight]
username() // [!code highlight]
] // [!code highlight]
@@ -42,7 +38,7 @@ The username plugin wraps the email and password authenticator and adds username
<Step>
### Add the client plugin
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { usernameClient } from "better-auth/client/plugins"
@@ -68,7 +64,7 @@ To signup a user with username, you can use the `signUp.username` function provi
- `image`: The image of the user. (optional)
- `callbackURL`: The url to redirect to after the user has signed up. (optional)
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { usernameClient } from "better-auth/client/plugins"
const client = createAuthClient({
@@ -95,7 +91,7 @@ To signin a user with username, you can use the `signIn.username` function provi
- `password`: The password of the user.
- `callbackURL`: The url to redirect to after the user has signed in. (optional)
```ts title="client.ts" twoslash
```ts title="client.ts"
import { createAuthClient } from "better-auth/client"
import { usernameClient } from "better-auth/client/plugins"
const client = createAuthClient({

View File

@@ -1,15 +0,0 @@
import { betterAuth } from "better-auth";
import { organization, twoFactor } from "better-auth/plugins";
export const auth = betterAuth({
baseURL: "http://localhost:3000",
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
twoFactor({
issuer: "My App",
}),
organization(),
],
});

View File

@@ -44,8 +44,10 @@
"@tsparticles/engine": "^3.5.0",
"@tsparticles/react": "^3.0.0",
"@tsparticles/slim": "^3.5.0",
"@types/better-sqlite3": "^7.6.11",
"@vercel/og": "^0.6.3",
"better-auth": "workspace:*",
"better-sqlite3": "^11.3.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "1.0.0",

View File

@@ -23,6 +23,8 @@
"@oslojs/encoding": "^1.0.0",
"astro": "^4.15.9",
"better-auth": "workspace:*",
"@types/better-sqlite3": "^7.6.11",
"better-sqlite3": "^11.3.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk-solid": "^1.1.0",

View File

@@ -1,14 +1,12 @@
import { betterAuth } from "better-auth";
import { passkey, twoFactor } from "better-auth/plugins";
import Database from "better-sqlite3";
import { Resend } from "resend";
const resend = new Resend(import.meta.env.RESEND_API_KEY);
export const auth = betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
database: new Database("./db.sqlite"),
account: {
accountLinking: {
enabled: true,

View File

@@ -3,14 +3,12 @@ import { organization, passkey, twoFactor } from "better-auth/plugins";
import { reactInvitationEmail } from "./email/invitation";
import { reactResetPasswordEmail } from "./email/rest-password";
import { resend } from "./email/resend";
import Database from "better-sqlite3";
const from = process.env.BETTER_AUTH_EMAIL || "delivered@resend.dev";
const to = process.env.TEST_EMAIL || "";
export const auth = betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
database: new Database("./db.sqlite"),
emailAndPassword: {
enabled: true,
async sendResetPassword(token, user) {

View File

@@ -47,6 +47,8 @@
"@react-three/fiber": "^8.17.7",
"@tanstack/react-query": "^5.56.2",
"better-auth": "workspace:*",
"@types/better-sqlite3": "^7.6.11",
"better-sqlite3": "^11.3.0",
"better-call": "0.2.3-beta.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",

View File

@@ -1,10 +1,8 @@
import Database from "better-sqlite3";
import { betterAuth } from "better-auth";
export const auth = betterAuth({
database: {
provider: "sqlite",
url: "./sqlite.db",
},
database: new Database("./db.sqlite"),
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID || "",

View File

@@ -16,6 +16,8 @@
"@vee-validate/zod": "^4.13.2",
"@vueuse/core": "^11.1.0",
"better-auth": "workspace:*",
"@types/better-sqlite3": "^7.6.11",
"better-sqlite3": "^11.3.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"embla-carousel-vue": "^8.3.0",

View File

@@ -25,6 +25,8 @@
"dependencies": {
"@internationalized/date": "^3.5.5",
"better-auth": "workspace:*",
"@types/better-sqlite3": "^7.6.11",
"better-sqlite3": "^11.3.0",
"bits-ui": "^0.21.15",
"clsx": "^2.1.1",
"cmdk-sv": "^0.0.18",

View File

@@ -1,11 +1,9 @@
import { betterAuth } from "better-auth";
import { env } from "$env/dynamic/private";
import Database from "better-sqlite3";
export const auth = betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
database: new Database("./db.sqlite"),
socialProviders: {
google: {
clientId: env.GOOGLE_CLIENT_ID || "",

View File

@@ -55,10 +55,10 @@
"@prisma/client": "^5.19.1",
"@simplewebauthn/types": "^10.0.0",
"@types/better-sqlite3": "^7.6.11",
"better-sqlite3": "^11.3.0",
"@types/pg": "^8.11.6",
"@types/prompts": "^2.4.9",
"@types/react": "^18.3.3",
"better-sqlite3": "^11.3.0",
"drizzle-orm": "^0.33.0",
"happy-dom": "^15.7.4",
"hono": "^4.5.4",

View File

@@ -9,12 +9,10 @@ import { drizzle } from "drizzle-orm/better-sqlite3";
import Database from "better-sqlite3";
describe("adapter test", async () => {
const database = new Database(path.join(__dirname, "test.db"));
beforeEach(async () => {
const { runMigrations } = await getMigrations({
database: {
provider: "sqlite",
url: path.join(__dirname, "test.db"),
},
database,
});
await runMigrations();
});
@@ -22,8 +20,8 @@ describe("adapter test", async () => {
afterAll(async () => {
await fs.unlink(path.join(__dirname, "test.db"));
});
const sqlite = new Database(path.join(__dirname, "test.db"));
const db = drizzle(sqlite, {
const db = drizzle(database, {
schema: {
user,
},
@@ -35,10 +33,7 @@ describe("adapter test", async () => {
it("should create schema", async () => {
const res = await adapter.createSchema!({
database: {
provider: "sqlite",
url: ":memory:",
},
database: new Database(path.join(__dirname, "test.db")),
});
expect(res.code).toMatchSnapshot("__snapshots__/adapter.drizzle");
});

View File

@@ -6,116 +6,50 @@ import {
SqliteDialect,
} from "kysely";
import type { BetterAuthOptions } from "../../types";
import {
BetterAuthError,
MissingDependencyError,
} from "../../error/better-auth-error";
import Database from "better-sqlite3";
import { Pool as PostgresPool } from "pg";
export const getDialect = async (config: BetterAuthOptions) => {
if (!config.database) {
return undefined;
}
if ("createDriver" in config.database) {
return config.database;
}
export const createKyselyAdapter = async (config: BetterAuthOptions) => {
const db = config.database;
let dialect: Dialect | undefined = undefined;
if ("provider" in config.database) {
const provider = config.database.provider;
const connectionString = config.database?.url?.trim();
if (provider === "postgres") {
try {
const pg = await import("pg").catch(async (e) => {
throw new MissingDependencyError("pg");
});
const Pool = pg.default?.Pool || pg.Pool;
const pool = new Pool({
connectionString,
});
dialect = new PostgresDialect({
pool,
});
} catch (e) {
if (e instanceof TypeError) {
throw new BetterAuthError("Invalid database URL");
let databaseType: "sqlite" | "mysql" | "postgres" | undefined = undefined;
if ("createDriver" in db) {
dialect = db;
if (dialect instanceof SqliteDialect) {
databaseType = "sqlite";
}
throw e;
if (dialect instanceof MysqlDialect) {
databaseType = "mysql";
}
}
if (provider === "mysql") {
try {
const { createPool } = await import("mysql2/promise").catch(
async (e) => {
throw new MissingDependencyError("mysql2");
},
);
const params = new URL(connectionString);
const pool = createPool({
host: params.hostname,
user: params.username,
password: params.password,
database: params.pathname.split("/")[1],
port: Number(params.port),
});
dialect = new MysqlDialect({ pool });
} catch (e) {
if (e instanceof TypeError) {
throw new BetterAuthError("Invalid database URL");
}
throw e;
if (dialect instanceof PostgresDialect) {
databaseType = "postgres";
}
}
if (provider === "sqlite") {
try {
const database = await import("better-sqlite3").catch(async (e) => {
throw new MissingDependencyError("better-sqlite3");
});
const Database = database.default || database;
const db = new Database(connectionString);
if (db instanceof Database) {
dialect = new SqliteDialect({
database: db,
});
} catch (e) {
console.error(e);
throw new BetterAuthError(
"Failed to initialize SQLite. Make sure `better-sqlite3` is properly installed.",
);
databaseType = "sqlite";
}
}
}
return dialect;
};
export const createKyselyAdapter = async (config: BetterAuthOptions) => {
if ("provider" in config.database) {
const dialect = await getDialect(config);
if (!dialect) {
return dialect;
}
const db = new Kysely<any>({
dialect,
if ("getConnection" in db) {
dialect = new MysqlDialect({
pool: db,
});
return db;
databaseType = "mysql";
}
return null;
};
export const getDatabaseType = (config: BetterAuthOptions) => {
if ("provider" in config.database) {
return config.database.provider;
if (db instanceof PostgresPool) {
dialect = new PostgresDialect({
pool: db,
});
databaseType = "postgres";
}
if ("dialect" in config.database) {
if (config.database.dialect instanceof PostgresDialect) {
return "postgres";
}
if (config.database.dialect instanceof MysqlDialect) {
return "mysql";
}
if (config.database.dialect instanceof SqliteDialect) {
return "sqlite";
}
}
return "sqlite";
return {
kysely: dialect ? new Kysely({ dialect }) : null,
dialect,
databaseType,
};
};

View File

@@ -9,12 +9,10 @@ import { kyselyAdapter } from "..";
import { Kysely, SqliteDialect } from "kysely";
describe("adapter test", async () => {
const database = new Database(path.join(__dirname, "test.db"));
beforeEach(async () => {
const { runMigrations } = await getMigrations({
database: {
provider: "sqlite",
url: path.join(__dirname, "test.db"),
},
database,
});
await runMigrations();
});
@@ -39,10 +37,7 @@ describe("adapter test", async () => {
it("should create schema", async () => {
const res = await adapter.createSchema!({
database: {
provider: "sqlite",
url: ":memory:",
},
database: new Database(path.join(__dirname, "test-2.db")),
});
expect(res.code).toMatchSnapshot("__snapshots__/adapter.drizzle");
});

View File

@@ -4,6 +4,7 @@ import { prismaAdapter } from "..";
import { runAdapterTest } from "../../test";
import { twoFactor } from "../../../plugins";
import path from "path";
import Database from "better-sqlite3";
const db = new PrismaClient();
describe("adapter test", async () => {
@@ -13,23 +14,17 @@ describe("adapter test", async () => {
const adapter = prismaAdapter(db, {
provider: "sqlite",
});
const database = new Database(path.join(__dirname, "test.db"));
it("should create schema", async () => {
const res = await adapter.createSchema!({
database: {
provider: "sqlite",
url: ":memory:",
},
database,
});
expect(res.code).toMatchSnapshot("__snapshots__/adapter.prisma");
});
it("should work with plugins", async () => {
const res = await adapter.createSchema!({
database: {
provider: "sqlite",
url: ":memory:",
},
database,
plugins: [twoFactor()],
});
expect(res.code).toMatchSnapshot(

View File

@@ -7,10 +7,7 @@ import type { FieldAttribute, FieldType } from "../../db";
import { logger } from "../../utils/logger";
import type { BetterAuthOptions } from "../../types";
import { getSchema } from "./get-schema";
import {
createKyselyAdapter,
getDatabaseType,
} from "../../adapters/kysely-adapter/dialect";
import { createKyselyAdapter } from "../../adapters/kysely-adapter/dialect";
const postgresMap = {
string: ["character varying", "text"],
@@ -67,9 +64,10 @@ export function matchType(
export async function getMigrations(config: BetterAuthOptions) {
const betterAuthSchema = getSchema(config);
const dbType = getDatabaseType(config);
const db = await createKyselyAdapter(config);
if (!db) {
const { kysely: db, databaseType: dbType } =
await createKyselyAdapter(config);
if (!db || !dbType) {
logger.error("Invalid database configuration.");
process.exit(1);
}

View File

@@ -3,10 +3,7 @@ import { BetterAuthError } from "../error/better-auth-error";
import type { BetterAuthOptions } from "../types";
import type { Adapter } from "../types/adapter";
import { getAuthTables } from "./get-tables";
import {
createKyselyAdapter,
getDatabaseType,
} from "../adapters/kysely-adapter/dialect";
import { createKyselyAdapter } from "../adapters/kysely-adapter/dialect";
import { kyselyAdapter } from "../adapters/kysely-adapter";
export async function getAdapter(
@@ -21,8 +18,8 @@ export async function getAdapter(
return options.database;
}
const db = await createKyselyAdapter(options);
if (!db) {
const { kysely, databaseType } = await createKyselyAdapter(options);
if (!kysely) {
throw new BetterAuthError("Failed to initialize database adapter");
}
const tables = getAuthTables(options);
@@ -30,11 +27,11 @@ export async function getAdapter(
for (const table of Object.values(tables)) {
schema[table.tableName] = table.fields;
}
return kyselyAdapter(db, {
return kyselyAdapter(kysely, {
transform: {
schema,
date: true,
boolean: getDatabaseType(options) === "sqlite",
boolean: databaseType === "sqlite",
},
});
}

View File

@@ -1,23 +1,19 @@
import { describe, expect, it } from "vitest";
import { init } from "./init";
import Database from "better-sqlite3";
describe("init", async () => {
const database = new Database(":memory:");
it("should match config", () => {
const res = init({
database: {
provider: "sqlite",
url: ":memory:",
},
database,
});
expect(res).toMatchSnapshot();
});
it("should mount internal plugins", async () => {
const res = await init({
database: {
provider: "sqlite",
url: ":memory:",
},
database,
advanced: {
crossSubDomainCookies: {
enabled: true,
@@ -34,10 +30,7 @@ describe("init", async () => {
baseURL: "http://test.test",
};
const res = await init({
database: {
provider: "sqlite",
url: ":memory:",
},
database,
plugins: [
{
id: "test",

View File

@@ -29,7 +29,7 @@ export const init = async (opts: BetterAuthOptions) => {
const plugins = options.plugins || [];
const internalPlugins = getInternalPlugins(options);
const adapter = await getAdapter(options);
const db = (await createKyselyAdapter(options)) || null;
const { kysely: db } = await createKyselyAdapter(options);
const baseURL = getBaseURL(options.baseURL, options.basePath) || "";
const secret =

View File

@@ -8,6 +8,7 @@ import { getMigrations } from "../cli/utils/get-migration";
import { parseSetCookieHeader } from "../utils/cookies";
import type { SuccessContext } from "@better-fetch/fetch";
import { getAdapter } from "../db/utils";
import Database from "better-sqlite3";
export async function getTestInstance<O extends Partial<BetterAuthOptions>>(
options?: O,
@@ -31,10 +32,7 @@ export async function getTestInstance<O extends Partial<BetterAuthOptions>>(
},
},
secret: "better-auth.secret",
database: {
provider: "sqlite",
url: dbName,
},
database: new Database(dbName),
emailAndPassword: {
enabled: true,
},

View File

@@ -0,0 +1,5 @@
import type Database from "better-sqlite3";
import type { Pool } from "mysql2";
export type BetterSqlite3Database = Database.Database;
export type MysqlPool = Pool;

View File

@@ -1,10 +1,13 @@
import type { Dialect } from "kysely";
import type { Dialect, PostgresPool } from "kysely";
import type { Account, Session, User } from "../db/schema";
import type { BetterAuthPlugin } from "./plugins";
import type { OAuthProviderList } from "./provider";
import type { SocialProviders } from "../social-providers";
import type { RateLimit } from "./models";
import type { Adapter } from "./adapter";
import type Database from "better-sqlite3";
import type { Pool } from "mysql2";
import type { BetterSqlite3Database, MysqlPool } from "./database";
export interface BetterAuthOptions {
/**
@@ -60,10 +63,9 @@ export interface BetterAuthOptions {
* Database configuration
*/
database:
| {
provider: "postgres" | "sqlite" | "mysql";
url: string;
}
| PostgresPool
| MysqlPool
| BetterSqlite3Database
| Dialect
| Adapter;
/**

View File

@@ -30,6 +30,5 @@ export default defineConfig((env) => {
treeshake: true,
skipNodeModulesBundle: true,
target: "es2022",
noExternal: ["pg", "better-sqlite3", "mysql2"],
};
});

288
pnpm-lock.yaml generated
View File

@@ -285,9 +285,15 @@ importers:
'@hono/node-server':
specifier: ^1.12.2
version: 1.13.1(hono@4.6.3)
'@types/better-sqlite3':
specifier: ^7.6.11
version: 7.6.11
better-auth:
specifier: ^0.0.4
version: 0.0.4(react@18.3.1)(solid-js@1.9.1)(typescript@5.6.2)(vue@3.5.10)
specifier: workspace:*
version: link:../../../packages/better-auth
better-sqlite3:
specifier: ^11.3.0
version: 11.3.0
dotenv:
specifier: ^16.4.5
version: 16.4.5
@@ -353,6 +359,9 @@ importers:
'@noble/ciphers':
specifier: ^0.6.0
version: 0.6.0
'@types/better-sqlite3':
specifier: ^7.6.11
version: 7.6.11
better-auth:
specifier: workspace:*
version: link:../../packages/better-auth
@@ -375,9 +384,15 @@ importers:
dev/express:
dependencies:
'@types/better-sqlite3':
specifier: ^7.6.11
version: 7.6.11
better-auth:
specifier: workspace:*
version: link:../../packages/better-auth
better-sqlite3:
specifier: ^11.3.0
version: 11.3.0
express:
specifier: ^4.21.0
version: 4.21.0
@@ -520,12 +535,18 @@ importers:
'@tsparticles/slim':
specifier: ^3.5.0
version: 3.5.0
'@types/better-sqlite3':
specifier: ^7.6.11
version: 7.6.11
'@vercel/og':
specifier: ^0.6.3
version: 0.6.3
better-auth:
specifier: workspace:*
version: link:../packages/better-auth
better-sqlite3:
specifier: ^11.3.0
version: 11.3.0
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@@ -695,12 +716,18 @@ importers:
'@oslojs/encoding':
specifier: ^1.0.0
version: 1.1.0
'@types/better-sqlite3':
specifier: ^7.6.11
version: 7.6.11
astro:
specifier: ^4.15.9
version: 4.15.9(@types/node@20.16.9)(typescript@5.6.2)
better-auth:
specifier: workspace:*
version: link:../../packages/better-auth
better-sqlite3:
specifier: ^11.3.0
version: 11.3.0
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@@ -855,12 +882,18 @@ importers:
'@tanstack/react-query':
specifier: ^5.56.2
version: 5.56.2(react@19.0.0-rc-7771d3a7-20240827)
'@types/better-sqlite3':
specifier: ^7.6.11
version: 7.6.11
better-auth:
specifier: workspace:*
version: link:../../packages/better-auth
better-call:
specifier: 0.2.3-beta.2
version: 0.2.3-beta.2
better-sqlite3:
specifier: ^11.3.0
version: 11.3.0
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@@ -991,6 +1024,9 @@ importers:
'@radix-icons/vue':
specifier: ^1.0.0
version: 1.0.0(vue@3.5.9)
'@types/better-sqlite3':
specifier: ^7.6.11
version: 7.6.11
'@unovis/ts':
specifier: 1.4.3-beta.0
version: 1.4.3-beta.0
@@ -1006,6 +1042,9 @@ importers:
better-auth:
specifier: workspace:*
version: link:../../packages/better-auth
better-sqlite3:
specifier: ^11.3.0
version: 11.3.0
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@@ -1017,7 +1056,7 @@ importers:
version: 8.3.0(vue@3.5.9)
nuxt:
specifier: ^3.13.0
version: 3.13.2(@biomejs/biome@1.7.3)(@types/node@20.16.9)(typescript@5.6.1-rc)(vite@5.4.8)
version: 3.13.2(@biomejs/biome@1.7.3)(@types/node@20.16.9)(better-sqlite3@11.3.0)(typescript@5.6.1-rc)(vite@5.4.8)
radix-vue:
specifier: ^1.9.6
version: 1.9.6(vue@3.5.9)
@@ -1061,9 +1100,15 @@ importers:
'@internationalized/date':
specifier: ^3.5.5
version: 3.5.5
'@types/better-sqlite3':
specifier: ^7.6.11
version: 7.6.11
better-auth:
specifier: workspace:*
version: link:../../packages/better-auth
better-sqlite3:
specifier: ^11.3.0
version: 11.3.0
bits-ui:
specifier: ^0.21.15
version: 0.21.15(svelte@4.2.19)
@@ -2105,10 +2150,6 @@ packages:
resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==}
dev: false
/@chronark/access-policies@0.0.2:
resolution: {integrity: sha512-KNxuQFcjfKIekDVAMXCqR7FBUr0BPOpUZj11vCfsC9v2IRTS3WWYJgxRx1tiZ703sjz8BeLbBnZW9aj6IalUaQ==}
dev: false
/@cloudflare/kv-asset-handler@0.3.4:
resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==}
engines: {node: '>=16.13'}
@@ -3484,7 +3525,7 @@ packages:
peerDependencies:
react-hook-form: ^7.0.0
dependencies:
react-hook-form: 7.53.0(react@19.0.0-rc-7771d3a7-20240827)
react-hook-form: 7.53.0(react@18.3.1)
dev: false
/@humanwhocodes/config-array@0.13.0:
@@ -4295,24 +4336,6 @@ packages:
solid-js: 1.9.1
dev: false
/@nanostores/vue@0.10.0(nanostores@0.11.3)(vue@3.5.10):
resolution: {integrity: sha512-832RAUbzRfHPs1CdqVEwfvgB2+RD/INji4Zo8bUSEfRO2pQRMMeq479gydnohGpRaa0oNwlfKo7TGFXCghq/1g==}
engines: {node: ^18.0.0 || >=20.0.0}
peerDependencies:
'@nanostores/logger': '>=0.2.3'
'@vue/devtools-api': '>=6.5.0'
nanostores: '>=0.9.2'
vue: '>=3.3.1'
peerDependenciesMeta:
'@nanostores/logger':
optional: true
'@vue/devtools-api':
optional: true
dependencies:
nanostores: 0.11.3
vue: 3.5.10(typescript@5.6.2)
dev: false
/@nanostores/vue@0.10.0(nanostores@0.11.3)(vue@3.5.9):
resolution: {integrity: sha512-832RAUbzRfHPs1CdqVEwfvgB2+RD/INji4Zo8bUSEfRO2pQRMMeq479gydnohGpRaa0oNwlfKo7TGFXCghq/1g==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -5136,10 +5159,6 @@ packages:
'@oslojs/binary': 0.2.3
dev: false
/@oslojs/encoding@0.3.0:
resolution: {integrity: sha512-i374LSDXuo2l+waPlejutIkw1zOA1wWxpvaXwQgyGsr5eZwX29hH1KIKFopPTriR4DKH+7nL7c5wNx16a/6voQ==}
dev: false
/@oslojs/encoding@0.4.1:
resolution: {integrity: sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q==}
dev: false
@@ -5154,10 +5173,6 @@ packages:
'@oslojs/encoding': 0.4.1
dev: false
/@oslojs/oauth2@0.5.0:
resolution: {integrity: sha512-t70+e4EgnzTbU4MrUWXzqWN2A6RJrlSSvwwuBv6E0Ap6/nsIXrjsdRWeTcSvvXTcC6fi0YdWaqEWLipcEm2Cgw==}
dev: false
/@oxc-parser/wasm@0.1.0:
resolution: {integrity: sha512-oA7XhTbg9rRBJhIzxCNhJwYmON/9LFAH4GBQxl7HWmGSS6HTrb2t6Peq82nxY0W7knguH52neh9T7zs27FVvsQ==}
dev: false
@@ -9298,15 +9313,6 @@ packages:
engines: {node: '>=10.13.0'}
dev: false
/@ts-morph/common@0.24.0:
resolution: {integrity: sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==}
dependencies:
fast-glob: 3.3.2
minimatch: 9.0.5
mkdirp: 3.0.1
path-browserify: 1.0.1
dev: false
/@tsparticles/basic@3.5.0:
resolution: {integrity: sha512-oty33TxM2aHWrzcwWRic1bQ04KBCdpnvzv8JXEkx5Uyp70vgVegUbtKmwGki3shqKZIt3v2qE4I8NsK6onhLrA==}
dependencies:
@@ -9594,7 +9600,6 @@ packages:
resolution: {integrity: sha512-i8KcD3PgGtGBLl3+mMYA8PdKkButvPyARxA7IQAd6qeslht13qxb1zzO8dRCtE7U3IoJS782zDBAeoKiM695kg==}
dependencies:
'@types/node': 20.16.9
dev: true
/@types/body-parser@1.19.5:
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
@@ -10798,16 +10803,6 @@ packages:
- supports-color
dev: false
/@vue/compiler-core@3.5.10:
resolution: {integrity: sha512-iXWlk+Cg/ag7gLvY0SfVucU8Kh2CjysYZjhhP70w9qI4MvSox4frrP+vDGvtQuzIcgD8+sxM6lZvCtdxGunTAA==}
dependencies:
'@babel/parser': 7.25.6
'@vue/shared': 3.5.10
entities: 4.5.0
estree-walker: 2.0.2
source-map-js: 1.2.1
dev: false
/@vue/compiler-core@3.5.9:
resolution: {integrity: sha512-KE1sCdwqSKq0CQ/ltg3XnlMTKeinjegIkuFsuq9DKvNPmqLGdmI51ChZdGBBRXIvEYTLm8X/JxOuBQ1HqF/+PA==}
dependencies:
@@ -10817,33 +10812,12 @@ packages:
estree-walker: 2.0.2
source-map-js: 1.2.1
/@vue/compiler-dom@3.5.10:
resolution: {integrity: sha512-DyxHC6qPcktwYGKOIy3XqnHRrrXyWR2u91AjP+nLkADko380srsC2DC3s7Y1Rk6YfOlxOlvEQKa9XXmLI+W4ZA==}
dependencies:
'@vue/compiler-core': 3.5.10
'@vue/shared': 3.5.10
dev: false
/@vue/compiler-dom@3.5.9:
resolution: {integrity: sha512-gEAURwPo902AsJF50vl59VaWR+Cx6cX9SoqLYHu1jq9hDbmQlXvpZyYNIIbxa2JTJ+FD/oBQweVUwuTQv79KTg==}
dependencies:
'@vue/compiler-core': 3.5.9
'@vue/shared': 3.5.9
/@vue/compiler-sfc@3.5.10:
resolution: {integrity: sha512-to8E1BgpakV7224ZCm8gz1ZRSyjNCAWEplwFMWKlzCdP9DkMKhRRwt0WkCjY7jkzi/Vz3xgbpeig5Pnbly4Tow==}
dependencies:
'@babel/parser': 7.25.6
'@vue/compiler-core': 3.5.10
'@vue/compiler-dom': 3.5.10
'@vue/compiler-ssr': 3.5.10
'@vue/shared': 3.5.10
estree-walker: 2.0.2
magic-string: 0.30.11
postcss: 8.4.47
source-map-js: 1.2.1
dev: false
/@vue/compiler-sfc@3.5.9:
resolution: {integrity: sha512-kp9qawcTXakYm0TN6YAwH24IurSywoXh4fWhRbLu0at4UVyo994bhEzJlQn82eiyqtut4GjkQodSfn8drFbpZQ==}
dependencies:
@@ -10857,13 +10831,6 @@ packages:
postcss: 8.4.47
source-map-js: 1.2.1
/@vue/compiler-ssr@3.5.10:
resolution: {integrity: sha512-hxP4Y3KImqdtyUKXDRSxKSRkSm1H9fCvhojEYrnaoWhE4w/y8vwWhnosJoPPe2AXm5sU7CSbYYAgkt2ZPhDz+A==}
dependencies:
'@vue/compiler-dom': 3.5.10
'@vue/shared': 3.5.10
dev: false
/@vue/compiler-ssr@3.5.9:
resolution: {integrity: sha512-fb1g2mQv32QzIei76rlXRTz08Grw+ZzBXSQfHo4StGFutm/flyebw3dGJkexKwcU3GjX9s5fIGjEv/cjO8j8Yw==}
dependencies:
@@ -10908,39 +10875,17 @@ packages:
rfdc: 1.4.1
dev: false
/@vue/reactivity@3.5.10:
resolution: {integrity: sha512-kW08v06F6xPSHhid9DJ9YjOGmwNDOsJJQk0ax21wKaUYzzuJGEuoKNU2Ujux8FLMrP7CFJJKsHhXN9l2WOVi2g==}
dependencies:
'@vue/shared': 3.5.10
dev: false
/@vue/reactivity@3.5.9:
resolution: {integrity: sha512-88ApgNZ6yPYpyYkTfXzcbWk6O8+LrPRIpa/U4AdeTzpfRUO+EUt5jemnTBVSlAUNmlYY96xa5feUNEq+BouLog==}
dependencies:
'@vue/shared': 3.5.9
/@vue/runtime-core@3.5.10:
resolution: {integrity: sha512-9Q86I5Qq3swSkFfzrZ+iqEy7Vla325M7S7xc1NwKnRm/qoi1Dauz0rT6mTMmscqx4qz0EDJ1wjB+A36k7rl8mA==}
dependencies:
'@vue/reactivity': 3.5.10
'@vue/shared': 3.5.10
dev: false
/@vue/runtime-core@3.5.9:
resolution: {integrity: sha512-YAeP0zNkjSl5mEc1NxOg9qoAhLNbREElHAhfYbMXT57oF0ixehEEJWBhg2uvVxslCGh23JhpEAyMvJrJHW9WGg==}
dependencies:
'@vue/reactivity': 3.5.9
'@vue/shared': 3.5.9
/@vue/runtime-dom@3.5.10:
resolution: {integrity: sha512-t3x7ht5qF8ZRi1H4fZqFzyY2j+GTMTDxRheT+i8M9Ph0oepUxoadmbwlFwMoW7RYCpNQLpP2Yx3feKs+fyBdpA==}
dependencies:
'@vue/reactivity': 3.5.10
'@vue/runtime-core': 3.5.10
'@vue/shared': 3.5.10
csstype: 3.1.3
dev: false
/@vue/runtime-dom@3.5.9:
resolution: {integrity: sha512-5Oq/5oenpB9lw94moKvOHqBDEaMSyDmcu2HS8AtAT6/pwdo/t9fR9aVtLh6FzYGGqZR9yRfoHAN6P7goblq1aA==}
dependencies:
@@ -10949,16 +10894,6 @@ packages:
'@vue/shared': 3.5.9
csstype: 3.1.3
/@vue/server-renderer@3.5.10(vue@3.5.10):
resolution: {integrity: sha512-IVE97tt2kGKwHNq9yVO0xdh1IvYfZCShvDSy46JIh5OQxP1/EXSpoDqetVmyIzL7CYOWnnmMkVqd7YK2QSWkdw==}
peerDependencies:
vue: 3.5.10
dependencies:
'@vue/compiler-ssr': 3.5.10
'@vue/shared': 3.5.10
vue: 3.5.10(typescript@5.6.2)
dev: false
/@vue/server-renderer@3.5.9(vue@3.5.9):
resolution: {integrity: sha512-tbuUsZfMWGazR9LXLNiiDSTwkO8K9sLyR70diY+FbQmKmh7236PPz4jkTxymelV8D89IJUGtbfe4VdmpHkmuxg==}
peerDependencies:
@@ -10968,10 +10903,6 @@ packages:
'@vue/shared': 3.5.9
vue: 3.5.9(typescript@5.6.1-rc)
/@vue/shared@3.5.10:
resolution: {integrity: sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ==}
dev: false
/@vue/shared@3.5.9:
resolution: {integrity: sha512-8wiT/m0mnsLhTME0mPgc57jv+4TipRBSAAmheUdYgiOaO6AobZPNOmm87ub4np65VVDgLcWxc+Edc++5Wyz1uA==}
@@ -11871,14 +11802,6 @@ packages:
zip-stream: 6.0.1
dev: false
/arctic@2.0.0-next.5:
resolution: {integrity: sha512-5d2miFSz5v1rTD+OOS5vmzqwgdWXFRJrnjVV0WxfDaADmt0afpjHAOGN5kaNQoHMsEJs+gCidGM92VNhIf6Hng==}
dependencies:
'@oslojs/crypto': 0.6.0
'@oslojs/encoding': 0.3.0
'@oslojs/oauth2': 0.5.0
dev: false
/arctic@2.0.0-next.9:
resolution: {integrity: sha512-VUi47ekY8oWEa+NE4AcEl5fwZF5lMn0/PCQUsPieLP8wFVXVFR+vxDKESkMQg+d8Ffd7LBLXWW/DTIgvD8zRtw==}
dependencies:
@@ -12209,6 +12132,7 @@ packages:
/aws-ssl-profiles@1.1.2:
resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==}
engines: {node: '>= 6.0.0'}
dev: true
/axe-core@4.10.0:
resolution: {integrity: sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==}
@@ -12308,64 +12232,6 @@ packages:
/base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
/better-auth@0.0.4(react@18.3.1)(solid-js@1.9.1)(typescript@5.6.2)(vue@3.5.10):
resolution: {integrity: sha512-PR1bR6zbgNRkSHZAPQQEqaHpHMyASXwBU2IbDY60gDWJO72d3wBSCiOKQcSGJRxJ55O9jitHVMHqHcAtC0++0A==}
hasBin: true
dependencies:
'@better-fetch/fetch': 1.1.9
'@better-fetch/logger': 1.1.3
'@chronark/access-policies': 0.0.2
'@nanostores/query': 0.3.4(nanostores@0.11.3)
'@nanostores/react': 0.7.3(nanostores@0.11.3)(react@18.3.1)
'@nanostores/solid': 0.4.2(nanostores@0.11.3)(solid-js@1.9.1)
'@nanostores/vue': 0.10.0(nanostores@0.11.3)(vue@3.5.10)
'@noble/ciphers': 0.6.0
'@noble/hashes': 1.5.0
'@paralleldrive/cuid2': 2.2.2
'@simplewebauthn/browser': 10.0.0
'@simplewebauthn/server': 10.0.1
arctic: 2.0.0-next.5
better-call: 0.1.38(typescript@5.6.2)
chalk: 5.3.0
commander: 12.1.0
consola: 3.2.3
dotenv: 16.4.5
jiti: 1.21.6
jose: 5.9.3
kysely: 0.27.4
mysql2: 3.11.3
nanostores: 0.11.3
oauth4webapi: 2.17.0
ora: 8.1.0
oslo: 1.2.1
pg: 8.13.0
prompts: 2.4.2
tiny-glob: 0.2.9
ts-morph: 23.0.0
zod: 3.23.8
transitivePeerDependencies:
- '@nanostores/logger'
- '@vue/devtools-api'
- encoding
- pg-native
- react
- solid-js
- typescript
- vue
dev: false
/better-call@0.1.38(typescript@5.6.2):
resolution: {integrity: sha512-Dx/T6/l1C1yDialymI+q3YN85lFPSwD35BvfsJxwD9G30lfwRSDS3uNKyYlykwacWBNLYrizmuMXnCxxu7oCBA==}
peerDependencies:
typescript: ^5.6.0-beta
dependencies:
'@better-fetch/fetch': 1.1.9
'@types/set-cookie-parser': 2.4.10
rou3: 0.5.1
set-cookie-parser: 2.7.0
typescript: 5.6.2
dev: false
/better-call@0.2.3-beta.10:
resolution: {integrity: sha512-yIb0lL6/XNOFEEon28wLdjDy/4oMKThFFt/5Tzz7xcwqqh++FwiLFIDwgVFP9pZYT4ytn6GdqQGQlFMe6ugaVg==}
dependencies:
@@ -13022,10 +12888,6 @@ packages:
phenomenon: 1.6.0
dev: false
/code-block-writer@13.0.2:
resolution: {integrity: sha512-XfXzAGiStXSmCIwrkdfvc7FS5Dtj8yelCtyOf2p2skCAfvLd6zu0rGzuS9NSCO3bq1JKpFZ7tbKdKlcd5occQA==}
dev: false
/code-red@1.0.4:
resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==}
dependencies:
@@ -13965,7 +13827,7 @@ packages:
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
dev: false
/db0@0.1.4:
/db0@0.1.4(better-sqlite3@11.3.0):
resolution: {integrity: sha512-Ft6eCwONYxlwLjBXSJxw0t0RYtA5gW9mq8JfBXn9TtC0nDPlqePAhpv9v4g9aONBi6JI1OXHTKKkUYGd+BOrCA==}
peerDependencies:
'@libsql/client': ^0.5.2
@@ -13978,6 +13840,8 @@ packages:
optional: true
drizzle-orm:
optional: true
dependencies:
better-sqlite3: 11.3.0
dev: false
/debounce@1.2.1:
@@ -16264,6 +16128,7 @@ packages:
resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==}
dependencies:
is-property: 1.0.2
dev: true
/genfun@4.0.1:
resolution: {integrity: sha512-48yv1eDS5Qrz6cbSDBBik0u7jCgC/eA9eZrl9MIN1LfKzFTuGt6EHgr31YM8yT9cjb5BplXb4Iz3VtOYmgt8Jg==}
@@ -17512,6 +17377,7 @@ packages:
/is-property@1.0.2:
resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
dev: true
/is-redirect@1.0.0:
resolution: {integrity: sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw==}
@@ -18290,6 +18156,7 @@ packages:
/long@5.2.3:
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
dev: true
/longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
@@ -18330,10 +18197,12 @@ packages:
/lru-cache@7.18.3:
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
engines: {node: '>=12'}
dev: true
/lru.min@1.1.1:
resolution: {integrity: sha512-FbAj6lXil6t8z4z3j0E5mfRlPzxkySotzUHwRXjlpRh10vc6AI6WN62ehZj82VG7M20rqogJ0GLwar2Xa05a8Q==}
engines: {bun: '>=1.0.0', deno: '>=1.30.0', node: '>=8.0.0'}
dev: true
/lucide-react@0.428.0(react@18.3.1):
resolution: {integrity: sha512-rGrzslfEcgqwh+TLBC5qJ8wvVIXhLvAIXVFKNHndYyb1utSxxn9rXOC+1CNJLi6yNOooyPqIs6+3YCp6uSiEvg==}
@@ -19489,12 +19358,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
/mkdirp@3.0.1:
resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
engines: {node: '>=10'}
hasBin: true
dev: false
/mlly@1.7.1:
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
dependencies:
@@ -19611,6 +19474,7 @@ packages:
named-placeholders: 1.1.3
seq-queue: 0.0.5
sqlstring: 2.3.3
dev: true
/mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
@@ -19624,6 +19488,7 @@ packages:
engines: {node: '>=12.0.0'}
dependencies:
lru-cache: 7.18.3
dev: true
/nanoassert@1.1.0:
resolution: {integrity: sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ==}
@@ -19792,7 +19657,7 @@ packages:
- babel-plugin-macros
dev: false
/nitropack@2.9.7:
/nitropack@2.9.7(better-sqlite3@11.3.0):
resolution: {integrity: sha512-aKXvtNrWkOCMsQbsk4A0qQdBjrJ1ZcvwlTQevI/LAgLWLYc5L7Q/YiYxGLal4ITyNSlzir1Cm1D2ZxnYhmpMEw==}
engines: {node: ^16.11.0 || >=17.0.0}
hasBin: true
@@ -19823,7 +19688,7 @@ packages:
cookie-es: 1.2.2
croner: 8.1.1
crossws: 0.2.4
db0: 0.1.4
db0: 0.1.4(better-sqlite3@11.3.0)
defu: 6.1.4
destr: 2.0.3
dot-prop: 8.0.2
@@ -20078,7 +19943,7 @@ packages:
hasBin: true
dev: false
/nuxt@3.13.2(@biomejs/biome@1.7.3)(@types/node@20.16.9)(typescript@5.6.1-rc)(vite@5.4.8):
/nuxt@3.13.2(@biomejs/biome@1.7.3)(@types/node@20.16.9)(better-sqlite3@11.3.0)(typescript@5.6.1-rc)(vite@5.4.8):
resolution: {integrity: sha512-Bjc2qRsipfBhjXsBEJCN+EUAukhdgFv/KoIR5HFB2hZOYRSqXBod3oWQs78k3ja1nlIhAEdBG533898KJxUtJw==}
engines: {node: ^14.18.0 || >=16.10.0}
hasBin: true
@@ -20127,7 +19992,7 @@ packages:
magic-string: 0.30.11
mlly: 1.7.1
nanotar: 0.1.1
nitropack: 2.9.7
nitropack: 2.9.7(better-sqlite3@11.3.0)
nuxi: 3.14.0
nypm: 0.3.12
ofetch: 1.4.0
@@ -22810,6 +22675,7 @@ packages:
/seq-queue@0.0.5:
resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==}
dev: true
/serialize-javascript@6.0.2:
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
@@ -23242,6 +23108,7 @@ packages:
/sqlstring@2.3.3:
resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==}
engines: {node: '>= 0.6'}
dev: true
/ssri@4.1.6:
resolution: {integrity: sha512-WUbCdgSAMQjTFZRWvSPpauryvREEA+Krn19rx67UlJEJx/M192ZHxMmJXjZ4tkdFm+Sb0SXGlENeQVlA5wY7kA==}
@@ -24182,13 +24049,6 @@ packages:
/ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
/ts-morph@23.0.0:
resolution: {integrity: sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==}
dependencies:
'@ts-morph/common': 0.24.0
code-block-writer: 13.0.2
dev: false
/tsconfck@3.1.3(typescript@5.6.2):
resolution: {integrity: sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==}
engines: {node: ^18 || >=20}
@@ -25750,22 +25610,6 @@ packages:
resolution: {integrity: sha512-J5+TwkayiBkieYBG8PGk5PMys8+UZxDmT/CCaX9otDzRONRr5hgTgo2Fha2krUFnUw1d576jsNGXhmAL06ixfA==}
dev: false
/vue@3.5.10(typescript@5.6.2):
resolution: {integrity: sha512-Vy2kmJwHPlouC/tSnIgXVg03SG+9wSqT1xu1Vehc+ChsXsRd7jLkKgMltVEFOzUdBr3uFwBCG+41LJtfAcBRng==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@vue/compiler-dom': 3.5.10
'@vue/compiler-sfc': 3.5.10
'@vue/runtime-dom': 3.5.10
'@vue/server-renderer': 3.5.10(vue@3.5.10)
'@vue/shared': 3.5.10
typescript: 5.6.2
dev: false
/vue@3.5.9(typescript@5.6.1-rc):
resolution: {integrity: sha512-nHzQhZ5cjFKynAY2beAm7XtJ5C13VKAFTLTgRYXy+Id1KEKBeiK6hO2RcW1hUjdbHMadz1YzxyHgQigOC54wug==}
peerDependencies: