import { App, type CreateAppConfig } from "bknd"; import { config as $config } from "bknd/core"; import type { MiddlewareHandler } from "hono"; import type { AdminControllerOptions } from "modules/server/AdminController"; export type BkndConfig = CreateAppConfig & { app?: CreateAppConfig | ((args: Args) => CreateAppConfig); onBuilt?: (app: App) => Promise; beforeBuild?: (app: App) => Promise; buildConfig?: Parameters[0]; }; export type FrameworkBkndConfig = BkndConfig; export type RuntimeBkndConfig = BkndConfig & { distPath?: string; }; export function makeConfig(config: BkndConfig, args?: Args): CreateAppConfig { let additionalConfig: CreateAppConfig = {}; if ("app" in config && config.app) { if (typeof config.app === "function") { if (!args) { throw new Error("args is required when config.app is a function"); } additionalConfig = config.app(args); } else { additionalConfig = config.app; } } return { ...config, ...additionalConfig }; } export async function createFrameworkApp( config: FrameworkBkndConfig, args?: Args ): Promise { const app = App.create(makeConfig(config, args)); if (config.onBuilt) { app.emgr.onEvent( App.Events.AppBuiltEvent, async () => { await config.onBuilt?.(app); }, "sync" ); } await config.beforeBuild?.(app); await app.build(config.buildConfig); return app; } export async function createRuntimeApp( { serveStatic, adminOptions, ...config }: RuntimeBkndConfig & { serveStatic?: MiddlewareHandler | [string, MiddlewareHandler]; adminOptions?: AdminControllerOptions | false; }, env?: Env ): Promise { const app = App.create(makeConfig(config, env)); app.emgr.onEvent( App.Events.AppBuiltEvent, async () => { if (serveStatic) { const [path, handler] = Array.isArray(serveStatic) ? serveStatic : [$config.server.assets_path + "*", serveStatic]; app.modules.server.get(path, handler); } await config.onBuilt?.(app); if (adminOptions !== false) { app.registerAdminController(adminOptions); } }, "sync" ); await config.beforeBuild?.(app); await app.build(config.buildConfig); return app; }