mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-15 20:17:22 +00:00
240 lines
7.0 KiB
Plaintext
240 lines
7.0 KiB
Plaintext
---
|
|
title: "Cloudflare"
|
|
description: "Run bknd inside Cloudflare Worker"
|
|
tags: ["documentation"]
|
|
---
|
|
|
|
## Installation
|
|
|
|
To get started with Cloudflare Workers and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
|
|
|
### CLI Starter
|
|
|
|
Create a new Cloudflare CLI starter project by running the following command:
|
|
|
|
```sh
|
|
npx bknd create -i cloudflare
|
|
```
|
|
|
|
### Manual
|
|
|
|
Create a new cloudflare worker project by following the [official guide](https://developers.cloudflare.com/workers/get-started/guide/), and then install bknd as a dependency:
|
|
|
|
<Tabs groupId='package-manager' persist items={[ 'npm', 'pnpm', 'yarn', 'bun']}>
|
|
|
|
```bash tab="npm"
|
|
npm install bknd
|
|
```
|
|
|
|
```bash tab="pnpm"
|
|
pnpm install bknd
|
|
```
|
|
|
|
```bash tab="yarn"
|
|
yarn add bknd
|
|
```
|
|
|
|
```bash tab="bun"
|
|
bun add bknd
|
|
```
|
|
|
|
</Tabs>
|
|
|
|
## Serve the API
|
|
|
|
If you don't choose anything specific, it uses the first D1 binding it finds.
|
|
|
|
```ts title="src/index.ts"
|
|
import { serve, d1 } from "bknd/adapter/cloudflare";
|
|
|
|
// scans your environment for the first D1 binding it finds
|
|
export default serve();
|
|
|
|
// manually specifying a D1 binding:
|
|
export default serve<Env>({
|
|
app: (env) => d1({ binding: env.D1_BINDING }),
|
|
});
|
|
|
|
// or specify binding using `bindings`
|
|
export default serve<Env>({
|
|
bindings: (env) => ({ db: env.D1_BINDING }),
|
|
});
|
|
|
|
// or use LibSQL
|
|
export default serve<Env>({
|
|
app: (env) => ({ url: env.DB_URL }),
|
|
});
|
|
```
|
|
|
|
For more information about the connection object when using LibSQL, refer to the [Database](/usage/database) guide.
|
|
|
|
Now run the worker:
|
|
|
|
```bash
|
|
wrangler dev
|
|
```
|
|
|
|
And confirm it works by opening [http://localhost:8787](http://localhost:8787) in
|
|
your browser.
|
|
|
|
## Serve the Admin UI
|
|
|
|
Now in order to also server the static admin files, you have to modify the `wrangler.toml` to include the static assets. You can do so by either serving the static using the new [Assets feature](https://developers.cloudflare.com/workers/static-assets/), or the deprecated [Workers Site](https://developers.cloudflare.com/workers/configuration/sites/configuration/).
|
|
|
|
### Assets (recommended)
|
|
|
|
Make sure your assets point to the static assets included in the bknd package:
|
|
|
|
```toml title="wrangler.toml"
|
|
assets = { directory = "node_modules/bknd/dist/static" }
|
|
```
|
|
|
|
### Workers Sites (legacy)
|
|
|
|
Make sure your site points to the static assets included in the bknd package:
|
|
|
|
```toml title="wrangler.toml"
|
|
[site]
|
|
bucket = "node_modules/bknd/dist/static"
|
|
```
|
|
|
|
And then modify the worker entry as follows:
|
|
|
|
```ts title="src/index.ts"
|
|
import { serve } from "bknd/adapter/cloudflare";
|
|
import manifest from "__STATIC_CONTENT_MANIFEST"; // [!code highlight]
|
|
|
|
export default serve<Env>({
|
|
app: () => ({
|
|
/* ... */
|
|
}),
|
|
assets: "kv", // [!code highlight]
|
|
manifest, // [!code highlight]
|
|
});
|
|
```
|
|
|
|
## Adding custom routes
|
|
|
|
You can also add custom routes by defining them after the app has been built, like so:
|
|
|
|
```ts
|
|
import { serve } from "bknd/adapter/cloudflare";
|
|
|
|
export default serve<Env>({
|
|
// ...
|
|
onBuilt: async (app) => {
|
|
app.server.get("/hello", (c) => c.json({ hello: "world" })); // [!code highlight]
|
|
},
|
|
});
|
|
```
|
|
|
|
The property `app.server` is a [Hono](https://hono.dev/) instance, you can literally anything you can do with Hono.
|
|
|
|
## D1 Sessions (experimental)
|
|
|
|
D1 now supports to enable [global read replication](https://developers.cloudflare.com/d1/best-practices/read-replication/). This allows to reduce latency by reading from the closest region. In order for this to work, D1 has to be started from a bookmark. You can enable this behavior on bknd by setting the `d1.session` property:
|
|
|
|
```typescript title="src/index.ts"
|
|
import { serve } from "bknd/adapter/cloudflare";
|
|
|
|
export default serve({
|
|
// ...
|
|
d1: {
|
|
// enables D1 sessions
|
|
session: true,
|
|
// (optional) restrict the transport, options: "header" | "cookie"
|
|
// if not specified, it supports both
|
|
transport: "cookie",
|
|
// (optional) choose session constraint if not bookmark present
|
|
// options: "first-primary" | "first-unconstrained"
|
|
first: "first-primary",
|
|
},
|
|
});
|
|
```
|
|
|
|
If bknd is used in a stateful user context (like in a browser), it'll automatically send the session cookie to the server to set the correct bookmark. If you need to manually set the bookmark, you can do so by setting the `x-cf-d1-session` header:
|
|
|
|
```bash
|
|
curl -H "x-cf-d1-session: <bookmark>" ...
|
|
```
|
|
|
|
## Filesystem access with Vite Plugin
|
|
The [Cloudflare Vite Plugin](https://developers.cloudflare.com/workers/vite-plugin/) allows to use Vite with Miniflare to emulate the Cloudflare Workers runtime. This is great, however, `unenv` disables any Node.js APIs that aren't supported, including the `fs` module. If you want to use plugins such as [`syncTypes`](/extending/plugins#synctypes), this will cause issues.
|
|
|
|
To fix this, bknd exports a Vite plugin that provides filesystem access during development. You can use it by adding the following to your `vite.config.ts` file:
|
|
|
|
```ts
|
|
import { devFsVitePlugin } from "bknd/adapter/cloudflare";
|
|
|
|
export default defineConfig({
|
|
plugins: [devFsVitePlugin()], // [!code highlight]
|
|
});
|
|
```
|
|
|
|
Now to use this polyfill, you can use the `devFsWrite` function to write files to the filesystem.
|
|
|
|
```ts
|
|
import { devFsWrite } from "bknd/adapter/cloudflare"; // [!code highlight]
|
|
import { syncTypes } from "bknd/plugins";
|
|
|
|
export default {
|
|
options: {
|
|
plugins: [
|
|
syncTypes({
|
|
write: async (et) => {
|
|
await devFsWrite("bknd-types.d.ts", et.toString()); // [!code highlight]
|
|
}
|
|
}),
|
|
]
|
|
},
|
|
} satisfies BkndConfig;
|
|
```
|
|
|
|
## Cloudflare Bindings in CLI
|
|
|
|
The bknd CLI does not automatically have access to the Cloudflare bindings. We need to manually proxy them to the CLI by using the `withPlatformProxy` helper function:
|
|
|
|
```typescript title="bknd.config.ts"
|
|
import { d1 } from "bknd/adapter/cloudflare";
|
|
import { withPlatformProxy } from "bknd/adapter/cloudflare/proxy";
|
|
|
|
export default withPlatformProxy({
|
|
app: (env) => ({
|
|
connection: d1({ binding: env.DB }),
|
|
}),
|
|
});
|
|
```
|
|
|
|
Now you can use the CLI with your Cloudflare resources.
|
|
|
|
<Callout type="warning">
|
|
Make sure to not import from this file in your app, as this would include `wrangler` as a dependency.
|
|
</Callout>
|
|
|
|
Instead, it's recommended to split this configuration into separate files, e.g. `bknd.config.ts` and `config.ts`:
|
|
|
|
```typescript title="config.ts"
|
|
import { d1, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";
|
|
|
|
export default {
|
|
app: (env) => ({
|
|
connection: d1({ binding: env.DB }),
|
|
}),
|
|
} satisfies CloudflareBkndConfig;
|
|
```
|
|
|
|
`config.ts` now holds the configuration, and can safely be imported in your app. Since the CLI looks for a `bknd.config.ts` file by default, we change it to wrap the configuration from `config.ts` in the `withPlatformProxy` helper function.
|
|
|
|
```typescript title="bknd.config.ts"
|
|
import { withPlatformProxy } from "bknd/adapter/cloudflare/proxy";
|
|
import config from "./config";
|
|
|
|
export default withPlatformProxy(config);
|
|
```
|
|
|
|
As an additional safe guard, you have to set a `PROXY` environment variable to `1` to enable the proxy.
|
|
|
|
```bash
|
|
PROXY=1 npx bknd types
|
|
```
|