2026-01-25 14:54:08 +00:00
|
|
|
import { Hono } from "hono"
|
2026-03-23 00:31:23 +00:00
|
|
|
import { cors } from "hono/cors"
|
2026-01-25 14:54:08 +00:00
|
|
|
|
2026-03-21 19:01:43 +00:00
|
|
|
import { registerAdminHttpHandlers } from "./admin/http.ts"
|
|
|
|
|
import { createRequireAdmin } from "./auth/admin-middleware.ts"
|
2026-01-25 16:21:00 +00:00
|
|
|
import { registerAuthHandlers } from "./auth/http.ts"
|
2026-03-16 01:30:02 +00:00
|
|
|
import { createAuth } from "./auth/index.ts"
|
|
|
|
|
import { createRequireSession } from "./auth/session-middleware.ts"
|
2026-04-11 16:34:11 +01:00
|
|
|
import { CalDavSourceProvider } from "./caldav/provider.ts"
|
2026-03-16 01:30:02 +00:00
|
|
|
import { createDatabase } from "./db/index.ts"
|
2026-03-15 22:57:19 +00:00
|
|
|
import { registerFeedHttpHandlers } from "./engine/http.ts"
|
2026-03-05 02:01:30 +00:00
|
|
|
import { createFeedEnhancer } from "./enhancement/enhance-feed.ts"
|
|
|
|
|
import { createLlmClient } from "./enhancement/llm-client.ts"
|
2026-06-13 01:59:54 +01:00
|
|
|
import { GoogleMapsSourceProvider } from "./google-maps/provider.ts"
|
2026-04-11 15:18:24 +01:00
|
|
|
import { CredentialEncryptor } from "./lib/crypto.ts"
|
2026-06-14 14:50:17 +01:00
|
|
|
import { ensureEnv } from "./lib/env.ts"
|
2026-02-22 20:59:19 +00:00
|
|
|
import { registerLocationHttpHandlers } from "./location/http.ts"
|
2026-03-16 01:30:02 +00:00
|
|
|
import { LocationSourceProvider } from "./location/provider.ts"
|
2026-06-14 00:05:19 +01:00
|
|
|
import { ReminderSourceProvider } from "./reminders/provider.ts"
|
2026-02-18 00:41:20 +00:00
|
|
|
import { UserSessionManager } from "./session/index.ts"
|
2026-03-22 17:57:54 +00:00
|
|
|
import { registerSourcesHttpHandlers } from "./sources/http.ts"
|
2026-03-29 15:34:50 +01:00
|
|
|
import { TflSourceProvider } from "./tfl/provider.ts"
|
2026-02-18 00:41:20 +00:00
|
|
|
import { WeatherSourceProvider } from "./weather/provider.ts"
|
2026-06-13 00:46:53 +01:00
|
|
|
import { WebSearchSourceProvider } from "./web-search/provider.ts"
|
2026-01-25 16:21:00 +00:00
|
|
|
|
2026-01-25 22:47:53 +00:00
|
|
|
function main() {
|
2026-06-14 14:50:17 +01:00
|
|
|
const env = ensureEnv(process.env)
|
2026-03-16 01:30:02 +00:00
|
|
|
|
2026-06-14 14:50:17 +01:00
|
|
|
const { db, close: closeDb } = createDatabase(env.databaseUrl)
|
|
|
|
|
const auth = createAuth(db)
|
2026-03-05 02:01:30 +00:00
|
|
|
|
2026-06-14 14:50:17 +01:00
|
|
|
const feedEnhancer = createFeedEnhancer({
|
|
|
|
|
client: createLlmClient({
|
|
|
|
|
apiKey: env.openrouterApiKey,
|
|
|
|
|
model: env.openrouterModel,
|
|
|
|
|
}),
|
|
|
|
|
})
|
2026-04-11 15:18:24 +01:00
|
|
|
|
2026-06-14 14:50:17 +01:00
|
|
|
const credentialEncryptor = new CredentialEncryptor(env.credentialEncryptionKey)
|
2026-06-13 01:59:54 +01:00
|
|
|
|
2026-03-05 02:01:30 +00:00
|
|
|
const sessionManager = new UserSessionManager({
|
2026-03-22 16:28:19 +00:00
|
|
|
db,
|
2026-03-05 02:01:30 +00:00
|
|
|
providers: [
|
2026-04-11 16:34:11 +01:00
|
|
|
new CalDavSourceProvider(),
|
2026-03-22 16:28:19 +00:00
|
|
|
new LocationSourceProvider(),
|
2026-06-14 00:05:19 +01:00
|
|
|
new ReminderSourceProvider({ db }),
|
2026-03-05 02:01:30 +00:00
|
|
|
new WeatherSourceProvider({
|
|
|
|
|
credentials: {
|
2026-06-14 14:50:17 +01:00
|
|
|
privateKey: env.weatherkitPrivateKey,
|
|
|
|
|
keyId: env.weatherkitKeyId,
|
|
|
|
|
teamId: env.weatherkitTeamId,
|
|
|
|
|
serviceId: env.weatherkitServiceId,
|
2026-03-05 02:01:30 +00:00
|
|
|
},
|
|
|
|
|
}),
|
2026-06-14 14:50:17 +01:00
|
|
|
new TflSourceProvider({ apiKey: env.tflApiKey }),
|
|
|
|
|
new WebSearchSourceProvider({ apiKey: env.exaApiKey }),
|
2026-06-13 01:59:54 +01:00
|
|
|
new GoogleMapsSourceProvider({
|
2026-06-14 14:50:17 +01:00
|
|
|
apiKey: env.googleMapsApiKey,
|
2026-06-13 01:59:54 +01:00
|
|
|
}),
|
2026-03-05 02:01:30 +00:00
|
|
|
],
|
|
|
|
|
feedEnhancer,
|
2026-04-11 15:18:24 +01:00
|
|
|
credentialEncryptor,
|
2026-03-05 02:01:30 +00:00
|
|
|
})
|
2026-02-18 00:41:20 +00:00
|
|
|
|
2026-01-25 22:47:53 +00:00
|
|
|
const app = new Hono()
|
2026-01-25 16:21:00 +00:00
|
|
|
|
2026-03-23 00:31:23 +00:00
|
|
|
const isDev = process.env.NODE_ENV !== "production"
|
|
|
|
|
const allowedOrigins = process.env.CORS_ORIGINS?.split(",").map((o) => o.trim()) ?? []
|
|
|
|
|
|
|
|
|
|
function resolveOrigin(origin: string): string | undefined {
|
|
|
|
|
if (isDev) return origin
|
|
|
|
|
return allowedOrigins.includes(origin) ? origin : undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app.use(
|
|
|
|
|
"/api/auth/*",
|
|
|
|
|
cors({
|
|
|
|
|
origin: resolveOrigin,
|
|
|
|
|
allowHeaders: ["Content-Type", "Authorization"],
|
|
|
|
|
allowMethods: ["POST", "GET", "OPTIONS"],
|
|
|
|
|
exposeHeaders: ["Content-Length"],
|
|
|
|
|
maxAge: 600,
|
|
|
|
|
credentials: true,
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
app.use(
|
|
|
|
|
"*",
|
|
|
|
|
cors({
|
|
|
|
|
origin: resolveOrigin,
|
|
|
|
|
credentials: true,
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
|
2026-01-25 22:47:53 +00:00
|
|
|
app.get("/health", (c) => c.json({ status: "ok" }))
|
|
|
|
|
|
2026-03-16 01:30:02 +00:00
|
|
|
const authSessionMiddleware = createRequireSession(auth)
|
2026-03-21 19:01:43 +00:00
|
|
|
const adminMiddleware = createRequireAdmin(auth)
|
2026-03-16 01:30:02 +00:00
|
|
|
|
|
|
|
|
registerAuthHandlers(app, auth)
|
2026-03-11 00:21:34 +00:00
|
|
|
|
2026-03-05 02:01:30 +00:00
|
|
|
registerFeedHttpHandlers(app, {
|
|
|
|
|
sessionManager,
|
2026-03-16 01:30:02 +00:00
|
|
|
authSessionMiddleware,
|
|
|
|
|
})
|
|
|
|
|
registerLocationHttpHandlers(app, { sessionManager, authSessionMiddleware })
|
2026-03-22 17:57:54 +00:00
|
|
|
registerSourcesHttpHandlers(app, { sessionManager, authSessionMiddleware })
|
2026-03-21 19:01:43 +00:00
|
|
|
registerAdminHttpHandlers(app, { sessionManager, adminMiddleware, db })
|
2026-03-16 01:30:02 +00:00
|
|
|
|
|
|
|
|
process.on("SIGTERM", async () => {
|
|
|
|
|
await closeDb()
|
|
|
|
|
process.exit(0)
|
2026-03-05 02:01:30 +00:00
|
|
|
})
|
2026-01-25 22:47:53 +00:00
|
|
|
|
|
|
|
|
return app
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const app = main()
|
2026-01-25 22:19:05 +00:00
|
|
|
|
2026-01-25 14:54:08 +00:00
|
|
|
export default {
|
|
|
|
|
port: 3000,
|
2026-06-12 16:31:28 +01:00
|
|
|
hostname: "0.0.0.0",
|
2026-01-25 14:54:08 +00:00
|
|
|
fetch: app.fetch,
|
|
|
|
|
}
|