import { DurableObject } from 'cloudflare:workers'; import { ensureAlarm, runAndRearm } from './alarm.ts'; import { ingest } from './index/ingest.ts'; import { IndexModel, type RecentOptions, type TrendingOptions } from './index/model.ts'; import { handleRequest } from './router.ts'; import { ingestDeps, outbound } from './services.ts'; export interface Env { INDEX: DurableObjectNamespace; APP_ORIGIN: string; JETSTREAM_URL: string; RELAY_URL: string; SLINGSHOT_URL: string; CONSTELLATION_URL: string; CONTACT_URL?: string; } export default { fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { return handleRequest(request, { ...env, fetch: outbound(env), cache: { match: (key) => caches.default.match(key), put: (key, response) => caches.default.put(key, response) }, waitUntil: (promise) => ctx.waitUntil(promise), }); }, }; /** * A Durable Object consuming `run.nibling.*` from Jetstream (D22). It's a cache, never the * source of truth — the author's PDS is — and the app must work with this absent. One global * instance (`getByName('global')`): the index is the whole network's `run.nibling.*` slice, * not sharded per account. */ export class Index extends DurableObject { #model: IndexModel; constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); this.#model = new IndexModel({ exec: >(query: string, ...bindings: unknown[]) => ctx.storage.sql.exec(query, ...bindings).toArray() as T[], }); void ctx.blockConcurrencyWhile(() => ensureAlarm(ctx.storage, Date.now())); } async getRecent(options: RecentOptions) { return this.#model.recent(options); } async getTrending(options: Omit) { return this.#model.trending({ ...options, now: Date.now() }); } async getKnown(dids: string[]) { return this.#model.known(dids); } /** No public HTTP surface; the Worker talks to this DO over RPC. */ override async fetch(): Promise { return new Response('not found', { status: 404 }); } async alarm(): Promise { await runAndRearm(this.ctx.storage, () => this.run(), Date.now); } async run(): Promise { await ingest(ingestDeps(this.env, this.#model, () => Date.now())); } }