Package Exports
- @batadata/serverless
Readme
@batadata/serverless
SQL-over-HTTP driver for BataDB — a serverless Postgres
platform. Query your database from edge functions, serverless runtimes, or any
environment with fetch, with no TCP connection to manage.
Works in Node.js, Vercel Edge Functions, Cloudflare Workers, Deno, and the browser.
Install
npm install @batadata/serverlessQuick start
import { neon } from '@batadata/serverless';
const sql = neon(
'postgresql://user:pass@ep-xxx.us-east-1.db.batadata.com/mydb',
{
apiKey: process.env.BATA_API_KEY, // bata_... (mint one with `bata api-keys create`)
projectId: 'proj_...',
branchId: 'br_...',
},
);
// Tagged-template queries are automatically parameterized ($1, $2, ...).
const userId = 42;
const rows = await sql`SELECT * FROM users WHERE id = ${userId}`;apiKey and apiUrl also fall back to the BATA_API_KEY and BATA_API_URL
environment variables, so in most deployments you only pass projectId and
branchId:
const sql = neon(connectionString, { projectId, branchId });Explicit queries and full result metadata
The tagged template returns just the rows. For row counts, the executed command,
or column names, use .query():
const result = await sql.query('SELECT id, email FROM users WHERE active = $1', [true]);
result.rows; // Array of row objects
result.rowCount; // number of rows
result.columns; // ['id', 'email']
result.command; // 'SELECT'Pool
A Pool is provided for API compatibility with pg/@neondatabase/serverless.
Over HTTP there is no real connection to pool, so end() is a no-op — it exists
so you can swap drivers without changing call sites.
import { Pool } from '@batadata/serverless';
const pool = new Pool({
connectionString: 'postgresql://user:pass@ep-xxx.db.batadata.com/mydb',
apiKey: process.env.BATA_API_KEY,
projectId: 'proj_...',
branchId: 'br_...',
});
const { rows } = await pool.query('SELECT * FROM users WHERE id = $1', [userId]);
await pool.end();Configuration
neon(connectionString, config) and new Pool(config) accept:
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
BATA_API_KEY env |
API key, sent as Authorization: Bearer <apiKey>. |
apiUrl |
string |
BATA_API_URL env, else https://api.batadata.com |
Control-plane base URL. The SQL endpoint is ${apiUrl}/v1/sql. |
projectId |
string |
— | Target project (x-project-id header). |
branchId |
string |
— | Target branch (x-branch-id header). |
timeout |
number |
10000 |
Per-request timeout in ms. |
fetchFunction |
typeof fetch |
globalThis.fetch |
Custom fetch (testing / runtimes without a global). |
headers |
Record<string,string> |
— | Extra headers on every request. |
fullResults |
boolean |
true |
Request column/command metadata from the server. |
Pool additionally accepts connectionString, or discrete host / port /
database / user / password / ssl fields.
Error handling
Failed queries throw a BataError carrying the HTTP status code:
import { BataError } from '@batadata/serverless';
try {
await sql`SELECT 1`;
} catch (err) {
if (err instanceof BataError) {
console.error(err.statusCode, err.message);
// e.g. 401 Query failed with status 401: {"error":"Invalid API key","code":"AUTH_INVALID_KEY"}
}
}TypeScript
Ships with type definitions. Row types are generic:
interface User { id: number; email: string }
const users = await sql<User>`SELECT id, email FROM users`;License
MIT