diff --git a/app/src/adapter/web/web.adapter.ts b/app/src/adapter/web/web.adapter.ts index 0ece4810..1a06b607 100644 --- a/app/src/adapter/web/web.adapter.ts +++ b/app/src/adapter/web/web.adapter.ts @@ -5,20 +5,44 @@ import { } 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> = FrameworkBkndConfig & { - adminOptions?: AdminControllerOptions | false; + /** + * 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 ` 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(config: WebBkndConfig, args?: Env) { let appPromise: Promise | undefined; - const { adminOptions, ...frameworkConfig } = config; + const { adminOptions, serveStatic, distPath, ...frameworkConfig } = config; async function getApp() { if (!appPromise) { if (adminOptions != null) { - appPromise = createRuntimeApp({ ...frameworkConfig, adminOptions }, args); + 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); }