mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-15 20:17:22 +00:00
Merge pull request #288 from bknd-io/feat/deno-and-docs
deno: add to cli starters, improve `serveStaticViaImport` and add deno to the docs
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import color from "picocolors";
|
||||
import { overridePackageJson, updateBkndPackages } from "./npm";
|
||||
import { type Template, templates, type TemplateSetupCtx } from "./templates";
|
||||
import { createScoped, flush } from "cli/utils/telemetry";
|
||||
import path from "node:path";
|
||||
|
||||
const config = {
|
||||
types: {
|
||||
@@ -20,6 +21,7 @@ const config = {
|
||||
node: "Node.js",
|
||||
bun: "Bun",
|
||||
cloudflare: "Cloudflare",
|
||||
deno: "Deno",
|
||||
aws: "AWS Lambda",
|
||||
},
|
||||
framework: {
|
||||
@@ -259,17 +261,19 @@ async function action(options: {
|
||||
}
|
||||
}
|
||||
|
||||
// update package name
|
||||
await overridePackageJson(
|
||||
(pkg) => ({
|
||||
...pkg,
|
||||
name: ctx.name,
|
||||
}),
|
||||
{ dir: ctx.dir },
|
||||
);
|
||||
$p.log.success(`Updated package name to ${color.cyan(ctx.name)}`);
|
||||
// update package name if there is a package.json
|
||||
if (fs.existsSync(path.resolve(ctx.dir, "package.json"))) {
|
||||
await overridePackageJson(
|
||||
(pkg) => ({
|
||||
...pkg,
|
||||
name: ctx.name,
|
||||
}),
|
||||
{ dir: ctx.dir },
|
||||
);
|
||||
$p.log.success(`Updated package name to ${color.cyan(ctx.name)}`);
|
||||
}
|
||||
|
||||
{
|
||||
if (template.installDeps !== false) {
|
||||
const install =
|
||||
options.yes ??
|
||||
(await $p.confirm({
|
||||
|
||||
@@ -93,17 +93,19 @@ export async function replacePackageJsonVersions(
|
||||
}
|
||||
|
||||
export async function updateBkndPackages(dir?: string, map?: Record<string, string>) {
|
||||
const versions = {
|
||||
bknd: await sysGetVersion(),
|
||||
...(map ?? {}),
|
||||
};
|
||||
await replacePackageJsonVersions(
|
||||
async (pkg) => {
|
||||
if (pkg in versions) {
|
||||
return versions[pkg];
|
||||
}
|
||||
return;
|
||||
},
|
||||
{ dir },
|
||||
);
|
||||
try {
|
||||
const versions = {
|
||||
bknd: await sysGetVersion(),
|
||||
...(map ?? {}),
|
||||
};
|
||||
await replacePackageJsonVersions(
|
||||
async (pkg) => {
|
||||
if (pkg in versions) {
|
||||
return versions[pkg];
|
||||
}
|
||||
return;
|
||||
},
|
||||
{ dir },
|
||||
);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
21
app/src/cli/commands/create/templates/deno.ts
Normal file
21
app/src/cli/commands/create/templates/deno.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { overrideJson } from "cli/commands/create/npm";
|
||||
import type { Template } from "cli/commands/create/templates";
|
||||
import { getVersion } from "cli/utils/sys";
|
||||
|
||||
export const deno = {
|
||||
key: "deno",
|
||||
title: "Deno Basic",
|
||||
integration: "deno",
|
||||
description: "A basic bknd Deno server with static assets",
|
||||
path: "gh:bknd-io/bknd/examples/deno",
|
||||
installDeps: false,
|
||||
ref: true,
|
||||
setup: async (ctx) => {
|
||||
const version = await getVersion();
|
||||
await overrideJson(
|
||||
"deno.json",
|
||||
(json) => ({ ...json, links: undefined, imports: { bknd: `npm:bknd@${version}` } }),
|
||||
{ dir: ctx.dir },
|
||||
);
|
||||
},
|
||||
} satisfies Template;
|
||||
@@ -1,3 +1,4 @@
|
||||
import { deno } from "cli/commands/create/templates/deno";
|
||||
import { cloudflare } from "./cloudflare";
|
||||
|
||||
export type TemplateSetupCtx = {
|
||||
@@ -15,6 +16,7 @@ export type Integration =
|
||||
| "react-router"
|
||||
| "astro"
|
||||
| "aws"
|
||||
| "deno"
|
||||
| "custom";
|
||||
|
||||
type TemplateScripts = "install" | "dev" | "build" | "start";
|
||||
@@ -34,6 +36,11 @@ export type Template = {
|
||||
* adds a ref "#{ref}" to the path. If "true", adds the current version of bknd
|
||||
*/
|
||||
ref?: true | string;
|
||||
/**
|
||||
* control whether to install dependencies automatically
|
||||
* e.g. on deno, this is not needed
|
||||
*/
|
||||
installDeps?: boolean;
|
||||
scripts?: Partial<Record<TemplateScripts, string>>;
|
||||
preinstall?: (ctx: TemplateSetupCtx) => Promise<void>;
|
||||
postinstall?: (ctx: TemplateSetupCtx) => Promise<void>;
|
||||
@@ -90,4 +97,5 @@ export const templates: Template[] = [
|
||||
path: "gh:bknd-io/bknd/examples/aws-lambda",
|
||||
ref: true,
|
||||
},
|
||||
deno,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
---
|
||||
title: "Deno"
|
||||
description: "Run bknd inside Deno"
|
||||
tags: ["documentation"]
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
To get started with Deno and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter:
|
||||
|
||||
### CLI Starter
|
||||
|
||||
Create a new Deno CLI starter project by running the following command:
|
||||
|
||||
```sh
|
||||
deno run npm:bknd create -i deno
|
||||
```
|
||||
|
||||
### Manual
|
||||
|
||||
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`, but it's the easiest way to serve the static assets.
|
||||
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,
|
||||
};
|
||||
```
|
||||
|
||||
In case you don't want to point your bknd dependency to the latest version, either add an `imports` section to your `deno.json` file:
|
||||
|
||||
```json title="deno.json"
|
||||
{
|
||||
"imports": {
|
||||
"bknd": "npm:bknd@<VERSION>" // [!code highlight]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or specify the package with the version specified to the `serveStaticViaImport` function:
|
||||
|
||||
```ts
|
||||
const app = await createRuntimeApp({
|
||||
serveStatic: serveStaticViaImport({
|
||||
package: "bknd@<VERSION>", // [!code highlight]
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
Replace `<VERSION>` with the version you want to use.
|
||||
|
||||
### `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,
|
||||
};
|
||||
```
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"pages": ["node", "bun", "cloudflare", "aws", "docker"]
|
||||
"pages": ["node", "bun", "cloudflare", "deno", "aws", "docker"]
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
3
examples/.gitignore
vendored
3
examples/.gitignore
vendored
@@ -1,2 +1,5 @@
|
||||
*/package-lock.json
|
||||
*/bun.lock
|
||||
*/deno.lock
|
||||
*/node_modules
|
||||
*/*.db
|
||||
11
examples/deno/deno.json
Normal file
11
examples/deno/deno.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"nodeModulesDir": "auto",
|
||||
"tasks": {
|
||||
"dev": "deno serve -A --watch main.ts"
|
||||
},
|
||||
"imports": {
|
||||
"bknd": "npm:bknd@0.19.0-rc.1"
|
||||
},
|
||||
"links": ["../../app/"],
|
||||
"unstable": ["raw-imports"]
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
import { createRuntimeApp } from "bknd/adapter";
|
||||
import { createRuntimeApp, serveStaticViaImport } from "bknd/adapter";
|
||||
|
||||
const app = await createRuntimeApp({
|
||||
connection: {
|
||||
url: "file:./data.db",
|
||||
},
|
||||
adminOptions: {
|
||||
// currently needs a hosted version of the static assets
|
||||
assetsPath: "https://cdn.bknd.io/bknd/static/0.15.0-rc.9/",
|
||||
},
|
||||
serveStatic: serveStaticViaImport(),
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
Deno.serve(app.fetch);
|
||||
export default {
|
||||
fetch: app.fetch,
|
||||
};
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "bknd-deno-example",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"bknd": "file:../../app"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user