mirror of
https://github.com/bknd-io/bknd/
synced 2026-08-03 08:36:01 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b070fb591e |
@@ -41,12 +41,12 @@ describe("postgres", () => {
|
|||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
if (!(await isPostgresRunning())) {
|
if (!(await isPostgresRunning())) {
|
||||||
await $`docker run --rm --name bknd-test-postgres -d -e POSTGRES_PASSWORD=${credentials.password} -e POSTGRES_USER=${credentials.user} -e POSTGRES_DB=${credentials.database} -p ${credentials.port}:5432 postgres:17`;
|
await $`docker run --rm --name bknd-test-postgres -d -e POSTGRES_PASSWORD=${credentials.password} -e POSTGRES_USER=${credentials.user} -e POSTGRES_DB=${credentials.database} -p ${credentials.port}:5432 postgres:17`;
|
||||||
await $waitUntil("Postgres is running", isPostgresRunning);
|
await $waitUntil("Postgres is running", isPostgresRunning, 500, 20);
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
}
|
}
|
||||||
|
|
||||||
disableConsoleLog();
|
disableConsoleLog();
|
||||||
});
|
}, 30000);
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (await isPostgresRunning()) {
|
if (await isPostgresRunning()) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ describe("AppAuth", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await app.build();
|
await app.build();
|
||||||
app.registerAdminController();
|
app.registerAdminController({ forceDev: true });
|
||||||
const spy = spyOn(app.module.auth.authenticator, "requestCookieRefresh");
|
const spy = spyOn(app.module.auth.authenticator, "requestCookieRefresh");
|
||||||
|
|
||||||
// register custom route
|
// register custom route
|
||||||
|
|||||||
@@ -340,11 +340,6 @@ async function buildAdapters() {
|
|||||||
platform: "node",
|
platform: "node",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
tsup.build({
|
|
||||||
...baseConfig("web"),
|
|
||||||
platform: "neutral",
|
|
||||||
}),
|
|
||||||
|
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig("node"),
|
...baseConfig("node"),
|
||||||
platform: "node",
|
platform: "node",
|
||||||
|
|||||||
@@ -278,11 +278,6 @@
|
|||||||
"import": "./dist/adapter/tanstack-start/index.js",
|
"import": "./dist/adapter/tanstack-start/index.js",
|
||||||
"require": "./dist/adapter/tanstack-start/index.js"
|
"require": "./dist/adapter/tanstack-start/index.js"
|
||||||
},
|
},
|
||||||
"./adapter/web": {
|
|
||||||
"types": "./dist/types/adapter/web/index.d.ts",
|
|
||||||
"import": "./dist/adapter/web/index.js",
|
|
||||||
"require": "./dist/adapter/web/index.js"
|
|
||||||
},
|
|
||||||
"./dist/main.css": "./dist/ui/main.css",
|
"./dist/main.css": "./dist/ui/main.css",
|
||||||
"./dist/styles.css": "./dist/ui/styles.css",
|
"./dist/styles.css": "./dist/ui/styles.css",
|
||||||
"./dist/manifest.json": "./dist/static/.vite/manifest.json",
|
"./dist/manifest.json": "./dist/static/.vite/manifest.json",
|
||||||
@@ -303,7 +298,6 @@
|
|||||||
"adapter/node": ["./dist/types/adapter/node/index.d.ts"],
|
"adapter/node": ["./dist/types/adapter/node/index.d.ts"],
|
||||||
"adapter/sveltekit": ["./dist/types/adapter/sveltekit/index.d.ts"],
|
"adapter/sveltekit": ["./dist/types/adapter/sveltekit/index.d.ts"],
|
||||||
"adapter/tanstack-start": ["./dist/types/adapter/tanstack-start/index.d.ts"],
|
"adapter/tanstack-start": ["./dist/types/adapter/tanstack-start/index.d.ts"],
|
||||||
"adapter/web": ["./dist/types/adapter/web/index.d.ts"],
|
|
||||||
"adapter/sqlite": ["./dist/types/adapter/sqlite/edge.d.ts"]
|
"adapter/sqlite": ["./dist/types/adapter/sqlite/edge.d.ts"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
export * from "./web.adapter";
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import { afterAll, beforeAll, describe, test, expect } from "bun:test";
|
|
||||||
import { createBknd } from "./web.adapter";
|
|
||||||
import type { WebBkndConfig } from "./web.adapter";
|
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
|
||||||
import { adapterTestSuite } from "adapter/adapter-test-suite";
|
|
||||||
import { bunTestRunner } from "adapter/bun/test";
|
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
|
||||||
afterAll(enableConsoleLog);
|
|
||||||
|
|
||||||
describe("web adapter via createBknd", () => {
|
|
||||||
adapterTestSuite(bunTestRunner, {
|
|
||||||
makeApp: (config, args) => createBknd(config, args).getApp(),
|
|
||||||
makeHandler: (config, args) => createBknd(config ?? {}, args).serve(),
|
|
||||||
});
|
|
||||||
|
|
||||||
test("caches app instance", async () => {
|
|
||||||
const bknd = createBknd({ connection: { url: ":memory:" } });
|
|
||||||
const app1 = await bknd.getApp();
|
|
||||||
const app2 = await bknd.getApp();
|
|
||||||
expect(app1).toBe(app2);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("getApi returns api", async () => {
|
|
||||||
const bknd = createBknd({ connection: { url: ":memory:" } });
|
|
||||||
const api = await bknd.getApi();
|
|
||||||
expect(api).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("serve returns a fetch handler", async () => {
|
|
||||||
const bknd = createBknd({ connection: { url: ":memory:" } });
|
|
||||||
const handler = bknd.serve();
|
|
||||||
const res = await handler(new Request("http://localhost:3000/api/system/config"));
|
|
||||||
expect(res.status).toBe(200);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("uses createRuntimeApp when adminOptions provided", async () => {
|
|
||||||
const bknd = createBknd({
|
|
||||||
connection: { url: ":memory:" },
|
|
||||||
adminOptions: { adminBasepath: "/admin" },
|
|
||||||
});
|
|
||||||
const app = await bknd.getApp();
|
|
||||||
expect(app).toBeDefined();
|
|
||||||
expect(app.isBuilt()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("uses createFrameworkApp when no adminOptions", async () => {
|
|
||||||
const bknd = createBknd({ connection: { url: ":memory:" } });
|
|
||||||
const app = await bknd.getApp();
|
|
||||||
expect(app).toBeDefined();
|
|
||||||
expect(app.isBuilt()).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
import {
|
|
||||||
createFrameworkApp,
|
|
||||||
createRuntimeApp,
|
|
||||||
type FrameworkBkndConfig,
|
|
||||||
} from "bknd/adapter";
|
|
||||||
import type { AdminControllerOptions } from "modules/server/AdminController";
|
|
||||||
import type { App } from "App";
|
|
||||||
import type { MiddlewareHandler } from "hono";
|
|
||||||
import { $console } from "bknd/utils";
|
|
||||||
|
|
||||||
export type WebBkndConfig<Env = Record<string, string | undefined>> = FrameworkBkndConfig<Env> & {
|
|
||||||
/**
|
|
||||||
* Serve the admin UI from the server. When omitted, render the admin UI
|
|
||||||
* client-side via `import { Admin } from "bknd/ui"` and `import "bknd/dist/styles.css"`.
|
|
||||||
*
|
|
||||||
* When provided, also set up static asset serving via one of:
|
|
||||||
* - `serveStatic` middleware (for Bun, Node, etc.)
|
|
||||||
* - `bknd copy-assets --out <static-dir>` postinstall script
|
|
||||||
* - `serveStaticViaImport()` from `bknd/adapter` (for edge/serverless)
|
|
||||||
*/
|
|
||||||
adminOptions?: AdminControllerOptions;
|
|
||||||
/** Hono middleware for serving bknd's bundled JS/CSS assets. */
|
|
||||||
serveStatic?: MiddlewareHandler | [string, MiddlewareHandler];
|
|
||||||
/** Override the path to bknd's dist folder (default: ./node_modules/bknd/dist) */
|
|
||||||
distPath?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function createBknd<Env>(config: WebBkndConfig<Env>, args?: Env) {
|
|
||||||
let appPromise: Promise<App> | undefined;
|
|
||||||
|
|
||||||
const { adminOptions, serveStatic, distPath, ...frameworkConfig } = config;
|
|
||||||
|
|
||||||
async function getApp() {
|
|
||||||
if (!appPromise) {
|
|
||||||
if (adminOptions != null) {
|
|
||||||
if (!serveStatic) {
|
|
||||||
$console.warn(
|
|
||||||
"adminOptions provided without serveStatic — admin UI assets may not be served. "
|
|
||||||
+ "See serveStatic, bknd copy-assets, or serveStaticViaImport.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
appPromise = createRuntimeApp(
|
|
||||||
{ ...frameworkConfig, adminOptions, serveStatic, distPath },
|
|
||||||
args,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
appPromise = createFrameworkApp(frameworkConfig, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return appPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getApi(opts?: { headers?: Headers; verify?: boolean }) {
|
|
||||||
const app = await getApp();
|
|
||||||
if (opts?.verify) {
|
|
||||||
const api = app.getApi({ headers: opts.headers });
|
|
||||||
await api.verifyAuth();
|
|
||||||
return api;
|
|
||||||
}
|
|
||||||
return app.getApi();
|
|
||||||
}
|
|
||||||
|
|
||||||
function serve() {
|
|
||||||
return async (req: Request) => {
|
|
||||||
const app = await getApp();
|
|
||||||
return app.fetch(req);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return { getApp, getApi, serve };
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"name": "bknd",
|
"name": "bknd",
|
||||||
"version": "0.21.0-rc.1",
|
"version": "0.20.0",
|
||||||
"bin": "./dist/cli/index.js",
|
"bin": "./dist/cli/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cfworker/json-schema": "^4.1.1",
|
"@cfworker/json-schema": "^4.1.1",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"@xyflow/react": "^12.9.2",
|
"@xyflow/react": "^12.9.2",
|
||||||
"aws4fetch": "^1.0.20",
|
"aws4fetch": "^1.0.20",
|
||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.19",
|
||||||
"fast-xml-parser": "^5.3.1",
|
"fast-xml-parser": "^5.3.1",
|
||||||
"hono": "4.10.4",
|
"hono": "4.10.4",
|
||||||
"json-schema-library": "10.0.0-rc7",
|
"json-schema-library": "10.0.0-rc7",
|
||||||
@@ -1812,7 +1812,7 @@
|
|||||||
|
|
||||||
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
|
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
|
||||||
|
|
||||||
"dayjs": ["dayjs@1.11.20", "", {}, "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="],
|
"dayjs": ["dayjs@1.11.19", "", {}, "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="],
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
{
|
{
|
||||||
"pages": ["nextjs", "react-router", "astro", "sveltekit", "tanstack-start", "vite", "nuxt", "web"]
|
"pages": [
|
||||||
|
"nextjs",
|
||||||
|
"react-router",
|
||||||
|
"astro",
|
||||||
|
"sveltekit",
|
||||||
|
"tanstack-start",
|
||||||
|
"vite",
|
||||||
|
"nuxt"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,210 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Web Adapter"
|
|
||||||
description: "Bring bknd to any web framework or runtime"
|
|
||||||
tags: ["documentation"]
|
|
||||||
---
|
|
||||||
|
|
||||||
## What is the Web Adapter?
|
|
||||||
|
|
||||||
The web adapter (`bknd/adapter/web`) is your universal connector. Use it to integrate bknd into **any** web framework or runtime — even ones without a dedicated adapter.
|
|
||||||
|
|
||||||
**Use the web adapter when:**
|
|
||||||
- Your framework doesn't have a dedicated bknd adapter
|
|
||||||
- You want full control over your server setup
|
|
||||||
- You're building a custom server or edge function
|
|
||||||
|
|
||||||
**Use a platform-specific adapter when:**
|
|
||||||
- You're using a supported framework (Next.js, SvelteKit, Nuxt, Astro, etc.)
|
|
||||||
- You prefer opinionated, zero-config setup
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
## Basic Setup
|
|
||||||
|
|
||||||
Create a config file and initialize the adapter:
|
|
||||||
|
|
||||||
```typescript title="bknd.config.ts"
|
|
||||||
import type { WebBkndConfig } from "bknd/adapter/web";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
connection: {
|
|
||||||
url: "file:data.db",
|
|
||||||
},
|
|
||||||
} satisfies WebBkndConfig;
|
|
||||||
```
|
|
||||||
|
|
||||||
```typescript title="src/bknd.ts"
|
|
||||||
import { createBknd } from "bknd/adapter/web";
|
|
||||||
import config from "../bknd.config";
|
|
||||||
|
|
||||||
export const bknd = createBknd(config, process.env);
|
|
||||||
```
|
|
||||||
|
|
||||||
`createBknd` returns three methods:
|
|
||||||
|
|
||||||
| Method | Returns | Description |
|
|
||||||
|--------|---------|-------------|
|
|
||||||
| `getApp()` | `Promise<App>` | The built bknd app instance (cached) |
|
|
||||||
| `getApi({ headers, verify })` | `Promise<Api>` | Convenience wrapper around `app.getApi()` |
|
|
||||||
| `serve()` | `(req: Request) => Promise<Response>` | A fetch handler for your server |
|
|
||||||
|
|
||||||
## Choosing an Admin UI Path
|
|
||||||
|
|
||||||
The web adapter supports two approaches to serving the admin UI:
|
|
||||||
|
|
||||||
| Path | Best For | How |
|
|
||||||
|------|----------|-----|
|
|
||||||
| **Client-side** (default) | React frameworks: Next.js, Astro, React Router, Tanstack Start | Import and render `<Admin />` in your own React route |
|
|
||||||
| **Server-side** | Non-React frameworks: SvelteKit, Nuxt, Bun, Node, Deno | The server serves the admin HTML and assets |
|
|
||||||
|
|
||||||
## Path 1: Client-Side Admin (Default)
|
|
||||||
|
|
||||||
For React-capable frameworks, render the admin UI directly in a route:
|
|
||||||
|
|
||||||
```tsx title="app/admin/[[...admin]]/page.tsx"
|
|
||||||
import { Admin } from "bknd/ui";
|
|
||||||
import "bknd/dist/styles.css";
|
|
||||||
import { bknd } from "@/bknd";
|
|
||||||
|
|
||||||
export default async function AdminPage() {
|
|
||||||
const api = await bknd.getApi({ verify: true });
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Admin
|
|
||||||
withProvider={{ user: api.getUser() }}
|
|
||||||
config={{ basepath: "/admin" }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
No server-side admin configuration needed. The admin UI runs entirely in the browser.
|
|
||||||
|
|
||||||
## Path 2: Server-Side Admin
|
|
||||||
|
|
||||||
For non-React frameworks or standalone servers, enable the admin controller:
|
|
||||||
|
|
||||||
```typescript title="src/bknd.ts"
|
|
||||||
import { createBknd } from "bknd/adapter/web";
|
|
||||||
import config from "../bknd.config";
|
|
||||||
|
|
||||||
export const bknd = createBknd({
|
|
||||||
...config,
|
|
||||||
adminOptions: {
|
|
||||||
adminBasepath: "/admin",
|
|
||||||
},
|
|
||||||
}, process.env);
|
|
||||||
```
|
|
||||||
|
|
||||||
You'll also need to serve the admin's static assets (JS, CSS). Choose one of three strategies:
|
|
||||||
|
|
||||||
### Strategy 1: serveStatic Middleware
|
|
||||||
|
|
||||||
**Best for:** Bun, Node, standalone servers with filesystem access
|
|
||||||
|
|
||||||
Use Hono's platform-specific `serveStatic` to serve assets from `node_modules/bknd/dist/static/`:
|
|
||||||
|
|
||||||
```typescript title="src/bknd.ts"
|
|
||||||
import { createBknd } from "bknd/adapter/web";
|
|
||||||
import { serveStatic } from "hono/bun"; // or "@hono/node-server/serve-static"
|
|
||||||
import config from "../bknd.config";
|
|
||||||
|
|
||||||
export const bknd = createBknd({
|
|
||||||
...config,
|
|
||||||
adminOptions: { adminBasepath: "/admin" },
|
|
||||||
serveStatic: serveStatic({ root: "./node_modules/bknd/dist/static" }),
|
|
||||||
}, process.env);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Strategy 2: copy-assets Postinstall
|
|
||||||
|
|
||||||
**Best for:** SvelteKit, Nuxt, any framework with a static directory
|
|
||||||
|
|
||||||
Copy assets at install time and let your framework serve them:
|
|
||||||
|
|
||||||
```json title="package.json"
|
|
||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"postinstall": "bknd copy-assets --out static"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Per-framework output paths:
|
|
||||||
|
|
||||||
| Framework | `--out` flag |
|
|
||||||
|-----------|-------------|
|
|
||||||
| SvelteKit | `--out static` |
|
|
||||||
| Nuxt | `--out public` |
|
|
||||||
| Next.js | `--out public` |
|
|
||||||
| Astro | `--out public` |
|
|
||||||
|
|
||||||
### Strategy 3: serveStaticViaImport
|
|
||||||
|
|
||||||
**Best for:** Edge/serverless runtimes (Deno Deploy, Cloudflare Workers)
|
|
||||||
|
|
||||||
For environments without filesystem access:
|
|
||||||
|
|
||||||
```typescript title="src/bknd.ts"
|
|
||||||
import { createBknd } from "bknd/adapter/web";
|
|
||||||
import { serveStaticViaImport } from "bknd/adapter";
|
|
||||||
import config from "../bknd.config";
|
|
||||||
|
|
||||||
export const bknd = createBknd({
|
|
||||||
...config,
|
|
||||||
adminOptions: { adminBasepath: "/admin" },
|
|
||||||
serveStatic: serveStaticViaImport(),
|
|
||||||
}, process.env);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Serving Requests
|
|
||||||
|
|
||||||
Use `bknd.serve()` as a fetch handler in your server:
|
|
||||||
|
|
||||||
```typescript title="server.ts"
|
|
||||||
import { bknd } from "./bknd";
|
|
||||||
|
|
||||||
// Bun
|
|
||||||
Bun.serve({ fetch: bknd.serve(), port: 3000 });
|
|
||||||
|
|
||||||
// Node (with @hono/node-server)
|
|
||||||
import { serve } from "@hono/node-server";
|
|
||||||
serve({ fetch: bknd.serve(), port: 3000 });
|
|
||||||
```
|
|
||||||
|
|
||||||
Or use `bknd.getApp()` to integrate with an existing Hono or other router setup.
|
|
||||||
|
|
||||||
## Reference: WebBkndConfig
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
type WebBkndConfig<Env> = FrameworkBkndConfig<Env> & {
|
|
||||||
/** Serve the admin UI from the server. Omit for client-side admin. */
|
|
||||||
adminOptions?: AdminControllerOptions;
|
|
||||||
|
|
||||||
/** Hono middleware for serving bknd's bundled JS/CSS assets. */
|
|
||||||
serveStatic?: MiddlewareHandler | [string, MiddlewareHandler];
|
|
||||||
|
|
||||||
/** Override path to bknd's dist folder (default: ./node_modules/bknd/dist) */
|
|
||||||
distPath?: string;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
@@ -45,8 +45,6 @@ bknd seamlessly integrates with popular frameworks, allowing you to use what you
|
|||||||
href="/integration/nuxt"
|
href="/integration/nuxt"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Card icon={<Icon icon="tabler:world" className="text-fd-primary !size-6" />} title="Web Adapter" href="/integration/web" />
|
|
||||||
|
|
||||||
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
||||||
Create a new issue to request a guide for your framework.
|
Create a new issue to request a guide for your framework.
|
||||||
</Card>
|
</Card>
|
||||||
@@ -110,8 +108,6 @@ If you prefer to use a runtime instead of a framework, you can choose from the f
|
|||||||
href="/integration/docker"
|
href="/integration/docker"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Card icon={<Icon icon="tabler:world" className="text-fd-primary !size-6" />} title="Web Adapter" href="/integration/web" />
|
|
||||||
|
|
||||||
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
||||||
Create a new issue to request a guide for your runtime.
|
Create a new issue to request a guide for your runtime.
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -185,8 +185,6 @@ Pick your framework or runtime to get started.
|
|||||||
href="/integration/docker"
|
href="/integration/docker"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Card icon={<Icon icon="tabler:world" className="text-fd-primary !size-6" />} title="Web Adapter" href="/integration/web" />
|
|
||||||
|
|
||||||
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
<Card title="Yours missing?" href="https://github.com/bknd-io/bknd/issues/new">
|
||||||
Create a new issue to request a guide for your runtime or framework.
|
Create a new issue to request a guide for your runtime or framework.
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user