Merge remote-tracking branch 'origin/release/0.20' into fork/jonaspm/fix/upload-media-entity-overwrite

This commit is contained in:
dswbx
2026-01-09 10:12:21 +01:00
226 changed files with 6748 additions and 2563 deletions

View File

@@ -261,3 +261,77 @@ export default {
```
### `emailOTP`
<Callout type="warning">
Make sure to setup proper permissions to restrict reading from the OTP entity. Also, this plugin requires the `email` driver to be registered.
</Callout>
A plugin that adds email OTP functionality to your app. It will add two endpoints to your app:
- `POST /api/auth/otp/login` to login a user with an OTP code
- `POST /api/auth/otp/register` to register a user with an OTP code
Both endpoints accept a JSON body with `email` (required) and `code` (optional). If `code` is provided, the OTP code will be validated and the user will be logged in or registered. If `code` is not provided, a new OTP code will be generated and sent to the user's email.
For example, to login an existing user with an OTP code, two requests are needed. The first one only with the email to generate and send the OTP code, and the second to send the users' email along with the OTP code. The last request will authenticate the user.
```http title="Generate OTP code to login"
POST /api/auth/otp/login
Content-Type: application/json
{
"email": "test@example.com"
}
```
If the user exists, an email will be sent with the OTP code, and the response will be a `201 Created`.
```http title="Login with OTP code"
POST /api/auth/otp/login
Content-Type: application/json
{
"email": "test@example.com",
"code": "123456"
}
```
If the code is valid, the user will be authenticated by sending a `Set-Cookie` header and a body property `token` with the JWT token (equally to the login endpoint).
```typescript title="bknd.config.ts"
import { emailOTP } from "bknd/plugins";
import { resendEmail } from "bknd";
export default {
options: {
drivers: {
// an email driver is required
email: resendEmail({ /* ... */}),
},
plugins: [
// all options are optional
emailOTP({
// the base path for the API endpoints
apiBasePath: "/api/auth/otp",
// the TTL for the OTP tokens in seconds
ttl: 600,
// the name of the OTP entity
entity: "users_otp",
// customize the email content
generateEmail: (otp) => ({
subject: "OTP Code",
body: `Your OTP code is: ${otp.code}`,
}),
// customize the code generation
generateCode: (user) => {
return Math.floor(100000 + Math.random() * 900000).toString();
},
})
],
},
} satisfies BkndConfig;
```
<AutoTypeTable path="../app/src/plugins/auth/email-otp.plugin.ts" name="EmailOTPPluginOptions" />

View File

@@ -188,64 +188,58 @@ export default serve<Env>({
### SQLocal
To use bknd with `sqlocal` for a offline expierence, you need to install the `@bknd/sqlocal` package. You can do so by running the following command:
To use bknd with `sqlocal` for a offline expierence, you need to install the `sqlocal` package. You can do so by running the following command:
```bash
npm install @bknd/sqlocal
npm install sqlocal
```
This package uses `sqlocal` under the hood. Consult the [sqlocal documentation](https://sqlocal.dallashoffman.com/guide/setup) for connection options:
Consult the [sqlocal documentation](https://sqlocal.dallashoffman.com/guide/setup) for connection options:
```js
import { createApp } from "bknd";
import { SQLocalConnection } from "@bknd/sqlocal";
```ts
import { createApp, sqlocal } from "bknd";
import { SQLocalKysely } from "sqlocal/kysely";
const app = createApp({
connection: new SQLocalConnection({
databasePath: ":localStorage:",
verbose: true,
}),
connection: sqlocal(new SQLocalKysely(":localStorage:")),
});
```
## PostgreSQL
To use bknd with Postgres, you need to install the `@bknd/postgres` package. You can do so by running the following command:
```bash
npm install @bknd/postgres
```
You can connect to your Postgres database using `pg` or `postgres` dialects. Additionally, you may also define your custom connection.
Postgres is built-in to bknd, you can connect to your Postgres database using `pg` or `postgres` dialects. Additionally, you may also define your custom connection.
### Using `pg`
To establish a connection to your database, you can use any connection options available on the [`pg`](https://node-postgres.com/apis/client) package.
To establish a connection to your database, you can use any connection options available on the [`pg`](https://node-postgres.com/apis/client) package. Wrap the `Pool` in the `pg` function to create a connection.
```js
```ts
import { serve } from "bknd/adapter/node";
import { pg } from "@bknd/postgres";
import { pg } from "bknd";
import { Pool } from "pg";
/** @type {import("bknd/adapter/node").NodeBkndConfig} */
const config = {
serve({
connection: pg({
connectionString: "postgresql://user:password@localhost:5432/database",
pool: new Pool({
connectionString: "postgresql://user:password@localhost:5432/database",
}),
}),
};
serve(config);
});
```
### Using `postgres`
To establish a connection to your database, you can use any connection options available on the [`postgres`](https://github.com/porsager/postgres) package.
To establish a connection to your database, you can use any connection options available on the [`postgres`](https://github.com/porsager/postgres) package. Wrap the `Sql` in the `postgresJs` function to create a connection.
```js
```ts
import { serve } from "bknd/adapter/node";
import { postgresJs } from "@bknd/postgres";
import { postgresJs } from "bknd";
import postgres from 'postgres'
serve({
connection: postgresJs("postgresql://user:password@localhost:5432/database"),
connection: postgresJs({
postgres: postgres("postgresql://user:password@localhost:5432/database"),
}),
});
```
@@ -255,8 +249,8 @@ Several Postgres hosting providers offer their own clients to connect to their d
Example using `@neondatabase/serverless`:
```js
import { createCustomPostgresConnection } from "@bknd/postgres";
```ts
import { createCustomPostgresConnection } from "bknd";
import { NeonDialect } from "kysely-neon";
const neon = createCustomPostgresConnection("neon", NeonDialect);
@@ -270,8 +264,8 @@ serve({
Example using `@xata.io/client`:
```js
import { createCustomPostgresConnection } from "@bknd/postgres";
```ts
import { createCustomPostgresConnection } from "bknd";
import { XataDialect } from "@xata.io/kysely";
import { buildClient } from "@xata.io/client";

View File

@@ -213,9 +213,9 @@ To use it, you have to wrap your configuration in a mode helper, e.g. for `code`
import { code, type CodeMode } from "bknd/modes";
import { type BunBkndConfig, writer } from "bknd/adapter/bun";
const config = {
export default code<BunBkndConfig>({
// some normal bun bknd config
connection: { url: "file:test.db" },
connection: { url: "file:data.db" },
// ...
// a writer is required, to sync the types
writer,
@@ -227,9 +227,7 @@ const config = {
force: true,
drop: true,
}
} satisfies CodeMode<BunBkndConfig>;
export default code(config);
});
```
Similarily, for `hybrid` mode:
@@ -238,9 +236,9 @@ Similarily, for `hybrid` mode:
import { hybrid, type HybridMode } from "bknd/modes";
import { type BunBkndConfig, writer, reader } from "bknd/adapter/bun";
const config = {
export default hybrid<BunBkndConfig>({
// some normal bun bknd config
connection: { url: "file:test.db" },
connection: { url: "file:data.db" },
// ...
// reader/writer are required, to sync the types and config
writer,
@@ -262,7 +260,5 @@ const config = {
force: true,
drop: true,
},
} satisfies HybridMode<BunBkndConfig>;
export default hybrid(config);
});
```