main.ts

2.1 KB · raw

1import { join } from "node:path";2import type { Hono } from "hono";3import { createSetupApp } from "./admin/setup.ts";4import { openBucket } from "./bucket/reader.ts";5import { startSyncLoop } from "./bucket/sync.ts";6import { warmAtlas } from "./pages/atlas.ts";7import { createApp } from "./server/app.ts";8import { startBackupLoop } from "./server/backup.ts";9import { CONFIG_FILE, type Config, ConfigError, loadConfig } from "./server/config.ts";10import { oneTimeCode } from "./server/connect.ts";11import { openKeprDb } from "./server/db.ts";12import { startMailLoop } from "./server/mail.ts";1314// Where a first-run setup puts Kepr's data, beside kepr.toml.15const DATA_DIR = "data";1617/** Starts the loops for a config and returns the app that serves it. */18function start(config: Config): Hono["fetch"] {19	const kepr = openKeprDb(config.dataDir);20	// One bucket for the sync loop and the app, so settings saved in the console reach both.21	const bucket = openBucket(config.bucket);22	startBackupLoop(kepr, config);23	startMailLoop(kepr, config);24	const mirrorDir = join(config.dataDir, "mirror");25	// The first visitor after a new save would otherwise wait a second or two on a big repo.26	startSyncLoop({27		bucket,28		kepr,29		mirrorDir,30		synced: (repo) => warmAtlas({ kepr, mirrorDir }, repo),31	});32	return createApp(config, kepr, bucket).fetch;33}3435try {36	let fetch: Hono["fetch"];37	if (await Bun.file(CONFIG_FILE).exists()) {38		fetch = start(await loadConfig(CONFIG_FILE));39	} else {40		const code = oneTimeCode();41		fetch = createSetupApp({42			code,43			configPath: CONFIG_FILE,44			dataDir: DATA_DIR,45			done: (config) => {46				fetch = start(config);47			},48		}).fetch;49		console.log(50			`kepr: no ${CONFIG_FILE} yet. Open /setup in a browser and enter the code ${code.slice(0, 4)}-${code.slice(4)}`,51		);52	}53	// Bun.serve reads the port from $PORT (default 3000).54	const server = Bun.serve({ fetch: (request, bun) => fetch(request, bun) });55	console.log(`kepr listening on ${server.url}`);56} catch (error) {57	if (!(error instanceof ConfigError)) throw error;58	console.error(`kepr: ${error.message}`);59	process.exit(1);60}