GET /xrpc/app.bsky.actor.searchActorsTypeahead
typeahead.waow.tech
1import { createClient, type Client } from "@libsql/client/web";
2import type { Env } from "./types";
3
4export interface Stmt {
5 bind(...args: unknown[]): Stmt;
6 all<T = Record<string, unknown>>(): Promise<{ results: T[] }>;
7 first<T = Record<string, unknown>>(): Promise<T | null>;
8 run(): Promise<{ meta: { changes: number } }>;
9}
10
11export interface TursoDB {
12 prepare(sql: string): Stmt;
13 batch(stmts: Stmt[], mode?: "write" | "read"): Promise<{ results: unknown[]; meta: { changes: number } }[]>;
14}
15
16export function tursoDb(client: Client): TursoDB {
17 return {
18 prepare(sql) {
19 let args: unknown[] = [];
20 const s: Stmt & { _sql: string; _args: () => unknown[] } = {
21 _sql: sql,
22 _args: () => args,
23 bind(...a) { args = a; return s; },
24 async all<T>() {
25 const r = await client.execute({ sql, args: args as any });
26 return { results: r.rows as unknown as T[] };
27 },
28 async first<T>() {
29 const r = await client.execute({ sql, args: args as any });
30 return (r.rows[0] as unknown as T) ?? null;
31 },
32 async run() {
33 const r = await client.execute({ sql, args: args as any });
34 return { meta: { changes: r.rowsAffected } };
35 },
36 };
37 return s;
38 },
39 async batch(stmts, mode = "write") {
40 const results = await client.batch(
41 stmts.map((s) => ({ sql: (s as any)._sql as string, args: (s as any)._args() as any[] })),
42 mode as any,
43 );
44 return results.map((r) => ({
45 results: r.rows as unknown[],
46 meta: { changes: r.rowsAffected },
47 }));
48 },
49 };
50}
51
52let cachedKey: string | undefined;
53let cachedClient: Client | undefined;
54let cachedDb: TursoDB | undefined;
55let initPromise: Promise<TursoDB> | undefined;
56
57/** lazy singleton — reuses the client across requests within a worker isolate */
58export function getDb(env: Env): Promise<TursoDB> {
59 const key = `${env.TURSO_URL}::${env.TURSO_AUTH_TOKEN}`;
60
61 if (cachedDb && cachedKey === key) return Promise.resolve(cachedDb);
62 if (initPromise && cachedKey === key) return initPromise;
63
64 cachedKey = key;
65 initPromise = (async () => {
66 const client = createClient({
67 url: env.TURSO_URL,
68 authToken: env.TURSO_AUTH_TOKEN,
69 });
70 const db = tursoDb(client);
71 cachedClient = client;
72 cachedDb = db;
73 return db;
74 })().catch((err) => {
75 if (cachedKey === key) {
76 cachedClient = undefined;
77 cachedDb = undefined;
78 initPromise = undefined;
79 }
80 throw err;
81 });
82
83 return initPromise;
84}