JSPM

@batadata/serverless

0.4.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 541
  • Score
    100M100P100Q86494F
  • License MIT

BataDB serverless driver — SQL-over-HTTP for edge functions (Turbine ORM PgCompatPool-conformant)

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/serverless

Quick 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