mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +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;
|
let files: string[] | undefined;
|
||||||
|
const pkg = opts?.package ?? "bknd";
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return async (c: Context, next: Next) => {
|
return async (c: Context, next: Next) => {
|
||||||
if (!files) {
|
if (!files) {
|
||||||
const manifest =
|
const manifest =
|
||||||
opts?.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 || [])]);
|
files = Object.values(manifest).flatMap((asset) => [asset.file, ...(asset.css || [])]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = c.req.path.substring(1);
|
const path = c.req.path.substring(1);
|
||||||
if (files.includes(path)) {
|
if (files.includes(path)) {
|
||||||
try {
|
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" },
|
with: { type: "text" },
|
||||||
}).then((m) => m.default);
|
}).then((m) => m.default);
|
||||||
|
|
||||||
@@ -183,7 +192,7 @@ export function serveStaticViaImport(opts?: { manifest?: Manifest }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} 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);
|
return c.text("File not found", 404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import color from "picocolors";
|
|||||||
import { overridePackageJson, updateBkndPackages } from "./npm";
|
import { overridePackageJson, updateBkndPackages } from "./npm";
|
||||||
import { type Template, templates, type TemplateSetupCtx } from "./templates";
|
import { type Template, templates, type TemplateSetupCtx } from "./templates";
|
||||||
import { createScoped, flush } from "cli/utils/telemetry";
|
import { createScoped, flush } from "cli/utils/telemetry";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
types: {
|
types: {
|
||||||
@@ -20,6 +21,7 @@ const config = {
|
|||||||
node: "Node.js",
|
node: "Node.js",
|
||||||
bun: "Bun",
|
bun: "Bun",
|
||||||
cloudflare: "Cloudflare",
|
cloudflare: "Cloudflare",
|
||||||
|
deno: "Deno",
|
||||||
aws: "AWS Lambda",
|
aws: "AWS Lambda",
|
||||||
},
|
},
|
||||||
framework: {
|
framework: {
|
||||||
@@ -259,7 +261,8 @@ async function action(options: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update package name
|
// update package name if there is a package.json
|
||||||
|
if (fs.existsSync(path.resolve(ctx.dir, "package.json"))) {
|
||||||
await overridePackageJson(
|
await overridePackageJson(
|
||||||
(pkg) => ({
|
(pkg) => ({
|
||||||
...pkg,
|
...pkg,
|
||||||
@@ -268,8 +271,9 @@ async function action(options: {
|
|||||||
{ dir: ctx.dir },
|
{ dir: ctx.dir },
|
||||||
);
|
);
|
||||||
$p.log.success(`Updated package name to ${color.cyan(ctx.name)}`);
|
$p.log.success(`Updated package name to ${color.cyan(ctx.name)}`);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
if (template.installDeps !== false) {
|
||||||
const install =
|
const install =
|
||||||
options.yes ??
|
options.yes ??
|
||||||
(await $p.confirm({
|
(await $p.confirm({
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ export async function replacePackageJsonVersions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function updateBkndPackages(dir?: string, map?: Record<string, string>) {
|
export async function updateBkndPackages(dir?: string, map?: Record<string, string>) {
|
||||||
|
try {
|
||||||
const versions = {
|
const versions = {
|
||||||
bknd: await sysGetVersion(),
|
bknd: await sysGetVersion(),
|
||||||
...(map ?? {}),
|
...(map ?? {}),
|
||||||
@@ -106,4 +107,5 @@ export async function updateBkndPackages(dir?: string, map?: Record<string, stri
|
|||||||
},
|
},
|
||||||
{ dir },
|
{ 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";
|
import { cloudflare } from "./cloudflare";
|
||||||
|
|
||||||
export type TemplateSetupCtx = {
|
export type TemplateSetupCtx = {
|
||||||
@@ -15,6 +16,7 @@ export type Integration =
|
|||||||
| "react-router"
|
| "react-router"
|
||||||
| "astro"
|
| "astro"
|
||||||
| "aws"
|
| "aws"
|
||||||
|
| "deno"
|
||||||
| "custom";
|
| "custom";
|
||||||
|
|
||||||
type TemplateScripts = "install" | "dev" | "build" | "start";
|
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
|
* adds a ref "#{ref}" to the path. If "true", adds the current version of bknd
|
||||||
*/
|
*/
|
||||||
ref?: true | string;
|
ref?: true | string;
|
||||||
|
/**
|
||||||
|
* control whether to install dependencies automatically
|
||||||
|
* e.g. on deno, this is not needed
|
||||||
|
*/
|
||||||
|
installDeps?: boolean;
|
||||||
scripts?: Partial<Record<TemplateScripts, string>>;
|
scripts?: Partial<Record<TemplateScripts, string>>;
|
||||||
preinstall?: (ctx: TemplateSetupCtx) => Promise<void>;
|
preinstall?: (ctx: TemplateSetupCtx) => Promise<void>;
|
||||||
postinstall?: (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",
|
path: "gh:bknd-io/bknd/examples/aws-lambda",
|
||||||
ref: true,
|
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"
|
href="/integration/cloudflare"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:deno" className="text-fd-primary !size-6" />}
|
||||||
|
title="Deno"
|
||||||
|
href="/integration/deno"
|
||||||
|
/>
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
icon={<Icon icon="tabler:lambda" className="text-fd-primary !size-6" />}
|
icon={<Icon icon="tabler:lambda" className="text-fd-primary !size-6" />}
|
||||||
title="AWS Lambda"
|
title="AWS Lambda"
|
||||||
|
|||||||
@@ -97,6 +97,12 @@ Start by using the integration guide for these popular frameworks/runtimes. Ther
|
|||||||
href="/integration/bun"
|
href="/integration/bun"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
icon={<Icon icon="simple-icons:deno" className="text-fd-primary !size-6" />}
|
||||||
|
title="Deno"
|
||||||
|
href="/integration/deno"
|
||||||
|
/>
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
icon={<Icon icon="tabler:lambda" className="text-fd-primary !size-6" />}
|
icon={<Icon icon="tabler:lambda" className="text-fd-primary !size-6" />}
|
||||||
title="AWS Lambda"
|
title="AWS Lambda"
|
||||||
|
|||||||
3
examples/.gitignore
vendored
3
examples/.gitignore
vendored
@@ -1,2 +1,5 @@
|
|||||||
*/package-lock.json
|
*/package-lock.json
|
||||||
*/bun.lock
|
*/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({
|
const app = await createRuntimeApp({
|
||||||
connection: {
|
connection: {
|
||||||
url: "file:./data.db",
|
url: "file:./data.db",
|
||||||
},
|
},
|
||||||
adminOptions: {
|
serveStatic: serveStaticViaImport(),
|
||||||
// currently needs a hosted version of the static assets
|
|
||||||
assetsPath: "https://cdn.bknd.io/bknd/static/0.15.0-rc.9/",
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// @ts-ignore
|
export default {
|
||||||
Deno.serve(app.fetch);
|
fetch: app.fetch,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "bknd-deno-example",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"bknd": "file:../../app"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user