just the currents, never the identities
1/**
2 * Driftline Analytics - Main HTTP entry point
3 *
4 * Anonymous analytics service for ATProto app views.
5 */
6
7import { Hono } from "https://esm.sh/hono@4.4.0";
8import { cors } from "https://esm.sh/hono@4.4.0/cors";
9import { runMigrations } from "./database/migrations.ts";
10import { admin } from "./routes/admin.ts";
11import { collector } from "./routes/collector.ts";
12import { stats } from "./routes/stats.ts";
13
14const app = new Hono();
15
16// Re-throw errors to see full stack traces
17app.onError((err, _c) => {
18 throw err;
19});
20
21// Enable CORS for client-side tracking
22app.use(
23 "*",
24 cors({
25 origin: "*",
26 allowMethods: ["GET", "POST", "OPTIONS"],
27 allowHeaders: ["Content-Type", "X-API-Key"],
28 }),
29);
30
31// Run migrations on startup
32let migrationsRan = false;
33app.use("*", async (_c, next) => {
34 if (!migrationsRan) {
35 await runMigrations();
36 migrationsRan = true;
37 }
38 await next();
39});
40
41// Health check
42app.get("/", (c) => {
43 return c.json({
44 service: "driftline-analytics",
45 status: "ok",
46 version: 1,
47 });
48});
49
50// Mount routes
51app.route("/admin", admin);
52app.route("/collect", collector);
53app.route("/stats", stats);
54
55// Export for Valtown HTTP trigger
56export default app.fetch;