Files
bknd/docs/content/docs/(documentation)/extending/plugins.mdx
T
dswbx 5ed1cf19b6 docs: plugins, cloudflare, sdk, elements, database (#240)
* docs: added plugins docs, updated cloudflare docs

* updated cli help text

* added `systemEntity` and added docs on how to work with system entities

* docs: added defaults to cloudflare image plugin

* docs: updated sdk and elements
2025-08-29 12:50:23 +02:00

212 lines
5.8 KiB
Plaintext

---
title: Plugins
tags: ["documentation"]
---
import { TypeTable } from 'fumadocs-ui/components/type-table';
bknd allows you to extend its functionality by creating plugins. These allows to hook into the app lifecycle and to provide a data structure that is guaranteed to be merged. A plugin is a function that takes in an instance of `App` and returns the following structure:
<AutoTypeTable path="../app/src/App.ts" name="AppPluginConfig" />
## Creating a simple plugin
To create a simple plugin which guarantees an entity `pages` to be available and an additioanl endpoint to render a html list of pages, you can create it as follows:
```tsx title="myPagesPlugin.tsx"
/** @jsxImportSource hono/jsx */
import { type App, type AppPlugin, em, entity, text } from "bknd";
export const myPagesPlugin: AppPlugin = (app) => ({
name: "my-pages-plugin",
// define the schema of the plugin
// this will always be merged into the app's schema
schema: () => em({
pages: entity("pages", {
title: text(),
content: text(),
}),
}),
// execute code after the app is built
onBuilt: () => {
// register a new endpoint, make sure that you choose an endpoint that is reachable for bknd
app.server.get("/my-pages", async (c) => {
const { data: pages } = await app.em.repo("pages").findMany({});
return c.html(
<body>
<h1>Pages: {pages.length}</h1>
<ul>
{pages.map((page: any) => (
<li key={page.id}>{page.title}</li>
))}
</ul>
</body>,
);
});
},
});
```
And then register it in your `bknd.config.ts` file:
```typescript
import type { BkndConfig } from "bknd/adapter";
import { myPagesPlugin } from "./myPagesPlugin";
export default {
options: {
plugins: [myPagesPlugin],
}
} satisfies BkndConfig;
```
The schema returned from the plugin will be merged into the schema of the app.
## Built-in plugins
bknd comes with a few built-in plugins that you can use.
### `syncTypes`
A simple plugin that writes down the TypeScript types of the data schema on boot and each build. The output is equivalent to running `npx bknd types`.
```typescript title="bknd.config.ts"
import { syncTypes } from "bknd/plugins";
import { writeFile } from "node:fs/promises";
export default {
options: {
plugins: [
syncTypes({
// whether to enable the plugin, make sure to disable in production
enabled: true,
// your writing function (required)
write: async (et) => {
await writeFile("bknd-types.d.ts", et.toString(), "utf-8");
}
}),
]
},
} satisfies BkndConfig;
```
### `syncConfig`
A simple plugin that writes down the app configuration on boot and each build.
```typescript title="bknd.config.ts"
import { syncConfig } from "bknd/plugins";
import { writeFile } from "node:fs/promises";
export default {
options: {
plugins: [
syncConfig({
// whether to enable the plugin, make sure to disable in production
enabled: true,
// your writing function (required)
write: async (config) => {
await writeFile("config.json", JSON.stringify(config, null, 2), "utf-8");
},
}),
]
},
} satisfies BkndConfig;
```
### `showRoutes`
A simple plugin that logs the routes of your app in the console.
```typescript title="bknd.config.ts"
import { showRoutes } from "bknd/plugins";
export default {
options: {
plugins: [
showRoutes({
// whether to show the routes only once (on first build)
once: true
})
],
},
} satisfies BkndConfig;
```
### `cloudflareImageOptimization`
A plugin that add Cloudflare Image Optimization to your app's media storage.
```typescript title="bknd.config.ts"
import { cloudflareImageOptimization } from "bknd/plugins";
export default {
options: {
plugins: [
cloudflareImageOptimization({
// the url to access the image optimization plugin
accessUrl: "/api/plugin/image/optimize",
// the path to resolve the image from, defaults to `/api/media/file`
resolvePath: "/api/media/file",
// for example, you may want to have default option to limit to a width of 1000px
defaultOptions: {
width: 1000,
}
})
],
},
} satisfies BkndConfig;
```
Here is a break down of all configuration options:
<AutoTypeTable path="../app/src/plugins/cloudflare/image-optimization.plugin.ts" name="CloudflareImageOptimizationOptions" />
When enabled, you can now access your images at your configured `accessUrl`. For example, if you have a media file at `/api/media/file/image.jpg`, you can access the optimized image at `/api/plugin/image/optimize/image.jpg` for optimization.
Now you can add query parameters for the transformations, e.g. `?width=1000&height=1000`.
<TypeTable
type={{
dpr: {
description:
'The device pixel ratio to use',
type: 'number',
default: 1,
},
fit: {
description: 'The fit mode to use',
type: '"scale-down" | "contain" | "cover" | "crop" | "pad"',
},
format: {
description: 'The format to use',
type: '"auto" | "avif" | "webp" | "jpeg" | "baseline-jpeg" | "json"'
},
height: {
description: 'The height to use',
type: 'number',
},
width: {
description: 'The width to use',
type: 'number',
},
metadata: {
description: 'The metadata to use',
type: '"copyright" | "keep" | "none"',
default: 'copyright'
},
quality: {
description: 'The quality to use',
type: 'number',
default: 85
},
}}
/>