Skip to content
fusion-db

The client

db is a Drizzle client over node-postgres. It is server-only: the package resolves a different module depending on the bundler's export condition.

Server implementation

The real client — the default (and SSR) condition. DATABASE_URL comes from the environment, and the full schema is attached so relational queries are typed:

index.ts
import { drizzle } from "drizzle-orm/node-postgres";
 
import * as schema from "./schema";
 
export const db = drizzle(process.env.DATABASE_URL!, { schema });
 
export * from "./schema";

Browser stub

Any client bundle resolves the browser condition to this stub. Every property access throws, so pg and its Node-only dependencies can never end up in the client bundle:

browser-stub.ts
/**
 * Browser-side stub for @tikab-interactive/fusion-db. The real Drizzle client requires the pg
 * Node driver which pulls in Buffer/events APIs that don't exist in browsers.
 * Any client-side import resolves to this stub, which throws if used.
 * Server-only code (createServerFn handlers, route loaders) hit the real
 * implementation because Vite picks the "node" export condition in SSR.
 */
const handler: ProxyHandler<object> = {
	get() {
		throw new Error(
			"@tikab-interactive/fusion-db is server-only. Access it from a createServerFn handler.",
		);
	},
};
 
export const db = new Proxy({}, handler) as never;
 
export * from "./schema";

Using it

Call it from a server function or route loader — never from a component. Drizzle operators like eq come from drizzle-orm; the tables come from fusion-db:

import { eq } from "drizzle-orm";
import { db, user } from "@tikab-interactive/fusion-db";
 
export async function getUser(id: string) {
  const [row] = await db.select().from(user).where(eq(user.id, id));
  return row;
}

If this runs in a browser bundle by mistake, the stub throws immediately with a clear "server-only" error rather than failing deep inside pg.