this repo has no description
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(db): use @libsql/client/web for remote Turso on Linux/deploy

Avoid native @libsql/linux-x64-gnu bindings that break under Deno Deploy's
Node compat layer. file: URLs still use the full client in dev only
(import.meta.env.DEV).

Made-with: Cursor

+46 -9
+4
README.md
··· 50 50 5. **Run command:** `deno task start` (or `deno serve -A _fresh/server.js` per 51 51 `deno.json`). 52 52 53 + Remote Turso (`libsql://…`) uses `@libsql/client/web` so the deploy runtime does 54 + not need native `@libsql/*` platform binaries. Local `file:./local.db` still 55 + uses the full client when running `deno task dev`. 56 + 53 57 Adjust if your host uses different entrypoints. 54 58 55 59 ## Contributing
+42 -9
lib/db.ts
··· 9 9 * 10 10 * If TURSO_DATABASE_URL is unset the client falls back to file:./local.db 11 11 * so `deno task dev` works without configuration. 12 + * 13 + * **Deploy note:** The default `@libsql/client` entry pulls native bindings 14 + * (`@libsql/linux-x64-gnu`, etc.) that break on Linux/serverless when the 15 + * bundle was resolved for another OS. Remote Turso URLs use 16 + * `@libsql/client/web` (HTTP only, no natives). Local `file:` URLs still 17 + * use the full client in dev only. 12 18 */ 13 - import { type Client, createClient } from "@libsql/client"; 19 + import type { Client } from "@libsql/client/web"; 14 20 15 21 let _client: Client | null = null; 22 + let _clientPromise: Promise<Client> | null = null; 16 23 let _migrated = false; 17 24 let _migrationPromise: Promise<void> | null = null; 18 25 ··· 24 31 } 25 32 } 26 33 27 - export function db(): Client { 28 - if (_client) return _client; 29 - const url = getEnv("TURSO_DATABASE_URL") ?? "file:./local.db"; 30 - const authToken = getEnv("TURSO_AUTH_TOKEN"); 31 - _client = createClient({ url, authToken }); 32 - return _client; 34 + function resolveDbUrl(): string { 35 + return getEnv("TURSO_DATABASE_URL") ?? "file:./local.db"; 36 + } 37 + 38 + /** 39 + * Production / `deno task start` must not load the native libsql binary; only 40 + * the web client. Vite sets import.meta.env.DEV in dev; omitting env is 41 + * treated as production (Deploy). 42 + */ 43 + function shouldLoadNativeFileClient(url: string): boolean { 44 + if (!url.startsWith("file:")) return false; 45 + return import.meta.env?.DEV === true; 46 + } 47 + 48 + function getClient(): Promise<Client> { 49 + if (_client) return Promise.resolve(_client); 50 + if (!_clientPromise) { 51 + _clientPromise = (async () => { 52 + const url = resolveDbUrl(); 53 + const authToken = getEnv("TURSO_AUTH_TOKEN"); 54 + if (shouldLoadNativeFileClient(url)) { 55 + const { createClient } = await import("@libsql/client"); 56 + _client = createClient({ url, authToken }) as unknown as Client; 57 + return _client; 58 + } 59 + const { createClient } = await import("@libsql/client/web"); 60 + _client = createClient({ url, authToken }); 61 + return _client; 62 + })(); 63 + } 64 + return _clientPromise; 33 65 } 34 66 35 67 const SCHEMA_STATEMENTS: string[] = [ ··· 111 143 if (_migrated) return Promise.resolve(); 112 144 if (_migrationPromise) return _migrationPromise; 113 145 _migrationPromise = (async () => { 114 - const c = db(); 146 + const c = await getClient(); 115 147 for (const stmt of SCHEMA_STATEMENTS) { 116 148 await c.execute(stmt); 117 149 } ··· 123 155 /** Convenience: ensure schema is in place before running a callback. */ 124 156 export async function withDb<T>(fn: (c: Client) => Promise<T>): Promise<T> { 125 157 await migrate(); 126 - return fn(db()); 158 + const c = await getClient(); 159 + return fn(c); 127 160 }