1import { join } from "node:path";2import type { Hono } from "hono";3import { createSetupApp } from "./admin/setup.ts";4import { startStorageLoop } from "./admin/storage.ts";5import { openBucket } from "./bucket/reader.ts";6import { startSyncWorker } from "./bucket/sync.ts";7import { openMirrors } from "./mirror/store.ts";8import { createApp } from "./server/app.ts";9import { startBackupLoop } from "./server/backup.ts";10import { CONFIG_FILE, type Config, ConfigError, loadConfig } from "./server/config.ts";11import { oneTimeCode } from "./server/connect.ts";12import { openKeprDb } from "./server/db.ts";13import { startMailLoop } from "./server/mail.ts";141516const DATA_DIR = "data";171819function start(config: Config): Hono["fetch"] {20 const kepr = openKeprDb(config.dataDir);21 22 const bucket = openBucket(config.bucket);23 startBackupLoop(kepr, config);24 startMailLoop(kepr, config);25 const mirrorDir = join(config.dataDir, "mirror");26 openMirrors(mirrorDir);27 28 const syncer = startSyncWorker(config.dataDir, config.bucket);29 startStorageLoop({ bucket, kepr, mirrorDir });30 return createApp(config, kepr, bucket, CONFIG_FILE, syncer).fetch;31}3233try {34 let fetch: Hono["fetch"];35 if (await Bun.file(CONFIG_FILE).exists()) {36 fetch = start(await loadConfig(CONFIG_FILE));37 } else {38 const code = oneTimeCode();39 fetch = createSetupApp({40 code,41 configPath: CONFIG_FILE,42 dataDir: DATA_DIR,43 done: (config) => {44 fetch = start(config);45 },46 }).fetch;47 console.log(48 `kepr: no ${CONFIG_FILE} yet. Open /setup in a browser and enter the code ${code.slice(0, 4)}-${code.slice(4)}`,49 );50 }51 52 const server = Bun.serve({ fetch: (request, bun) => fetch(request, bun) });53 console.log(`kepr listening on ${server.url}`);54} catch (error) {55 if (!(error instanceof ConfigError)) throw error;56 console.error(`kepr: ${error.message}`);57 process.exit(1);58}