feat: improve Deno support and enhance serveStaticViaImport function

- Introduced support for Deno as a runtime in the documentation.
- Updated serveStaticViaImport function to accept additional options: appendRaw and package.
- Improved error logging in serveStaticViaImport for better debugging.
- Added new Deno integration documentation with examples for serving static assets.
This commit is contained in:
dswbx
2025-10-24 18:22:58 +02:00
parent 88cc406002
commit 1fc6e810ae
5 changed files with 132 additions and 6 deletions

View File

@@ -154,23 +154,32 @@ export async function createRuntimeApp<Args = DefaultArgs>(
* });
* ```
*/
export function serveStaticViaImport(opts?: { manifest?: Manifest }) {
export function serveStaticViaImport(opts?: {
manifest?: Manifest;
appendRaw?: boolean;
package?: string;
}) {
let files: string[] | undefined;
const pkg = opts?.package ?? "bknd";
// @ts-ignore
return async (c: Context, next: Next) => {
if (!files) {
const manifest =
opts?.manifest ||
((await import("bknd/dist/manifest.json", { with: { type: "json" } }))
.default as Manifest);
((
await import(/* @vite-ignore */ `${pkg}/dist/manifest.json`, {
with: { type: "json" },
})
).default as Manifest);
files = Object.values(manifest).flatMap((asset) => [asset.file, ...(asset.css || [])]);
}
const path = c.req.path.substring(1);
if (files.includes(path)) {
try {
const content = await import(/* @vite-ignore */ `bknd/static/${path}?raw`, {
const url = `${pkg}/static/${path}${opts?.appendRaw ? "?raw" : ""}`;
const content = await import(/* @vite-ignore */ url, {
with: { type: "text" },
}).then((m) => m.default);
@@ -183,7 +192,7 @@ export function serveStaticViaImport(opts?: { manifest?: Manifest }) {
});
}
} catch (e) {
console.error("Error serving static file:", e);
console.error(`Error serving static file "${path}":`, String(e));
return c.text("File not found", 404);
}
}

View File

@@ -0,0 +1,105 @@
---
title: "Deno"
description: "Run bknd inside Deno"
tags: ["documentation"]
---
Deno is fully supported as a runtime for bknd. If you plan to solely use the API, the setup is pretty straightforward.
```ts title="main.ts"
import { createAdapterApp } from "npm:bknd/adapter";
const app = await createAdapterApp({
connection: {
url: "file:data.db",
},
});
export default {
fetch: app.fetch,
};
```
## Serve the Admin UI
In order to also serve the static assets of the admin UI, you have 3 choices:
1. Use the `serveStaticViaImport` function to serve the static assets from the `bknd` package directly (requires unstable `raw-imports`).
2. Copy the static assets to your local project and use Hono's `serveStatic` middleware.
3. Use the `adminOptions.assetsPath` property to point to a remote address with the static assets.
### `serveStaticViaImport`
The `serveStaticViaImport` function is a middleware that serves the static assets from the `bknd` package directly using dynamic raw imports. It requires the unstable `raw-imports` feature to be enabled. You can enable it by adding the following to your `deno.json`:
```json title="deno.json"
{
"unstable": ["raw-imports"]
}
```
Or by using the `--unstable-raw-imports` flag when running your script. Now create a `main.ts` file to serve the API and static assets:
```ts title="main.ts"
import { createRuntimeApp, serveStaticViaImport } from "bknd/adapter";
const app = await createRuntimeApp({
connection: {
url: "file:data.db",
},
serveStatic: serveStaticViaImport()
});
export default {
fetch: app.fetch,
};
```
### `serveStatic` from local files
You can also serve the static assets from your local project by using Hono's `serveStatic` middleware. You can do so by copying the static assets to your local project and using the `serveStatic` middleware. First, you have to copy the static assets, by running the following command:
```bash
deno run npm:bknd copy-assets --out public
```
This will copy the static assets to the `public` directory and then serve them from there:
```ts title="main.ts"
import { createRuntimeApp, serveStatic } from "bknd/adapter";
import { serveStatic } from "npm:hono/deno";
const app = await createRuntimeApp({
connection: {
url: "file:data.db",
},
serveStatic: serveStatic({
root: "./public",
}),
});
export default {
fetch: app.fetch,
};
```
### `adminOptions.assetsPath`
You can also use the `adminOptions.assetsPath` property to point to a remote address with the static assets. This is useful in case none of the other methods work for you.
```ts title="main.ts"
import { createRuntimeApp } from "bknd/adapter";
const app = await createRuntimeApp({
connection: {
url: "file:data.db",
},
adminOptions: {
assetsPath: "https://...",
},
});
export default {
fetch: app.fetch,
};
```

View File

@@ -1,3 +1,3 @@
{
"pages": ["node", "bun", "cloudflare", "aws", "docker"]
"pages": ["node", "bun", "cloudflare", "deno", "aws", "docker"]
}

View File

@@ -61,6 +61,12 @@ If you prefer to use a runtime instead of a framework, you can choose from the f
href="/integration/cloudflare"
/>
<Card
icon={<Icon icon="simple-icons:deno" className="text-fd-primary !size-6" />}
title="Deno"
href="/integration/deno"
/>
<Card
icon={<Icon icon="tabler:lambda" className="text-fd-primary !size-6" />}
title="AWS Lambda"

View File

@@ -97,6 +97,12 @@ Start by using the integration guide for these popular frameworks/runtimes. Ther
href="/integration/bun"
/>
<Card
icon={<Icon icon="simple-icons:deno" className="text-fd-primary !size-6" />}
title="Deno"
href="/integration/deno"
/>
<Card
icon={<Icon icon="tabler:lambda" className="text-fd-primary !size-6" />}
title="AWS Lambda"