SDKs

Node.js SDK

TypeScript-first client for servers, workers, CLIs, and serverless functions.

orbitnest-node is the official Node.js client. Fully typed, ESM-first, and compatible with both the anon key (for user-scoped apps with RLS) and the service_role key (for trusted backend workers).

Installation

bash
npm install orbitnest-node
# or
pnpm add orbitnest-node
# or
yarn add orbitnest-node

Initialize

typescript
import { createClient } from 'orbitnest-node';

// For user-scoped apps (respects RLS)
const client = createClient({
  projectUrl:  process.env.ORBITNEST_URL!,
  anonKey:     process.env.ORBITNEST_ANON_KEY!,
});

// For trusted backend work (bypasses RLS)
const admin = createClient({
  projectUrl:      process.env.ORBITNEST_URL!,
  serviceRoleKey:  process.env.ORBITNEST_SERVICE_ROLE_KEY!,
});

Database queries

typescript
// Select with filters
const { data: posts, error } = await client.from('posts')
  .select('id, title, author:users(name)')
  .eq('published', true)
  .order('created_at', { ascending: false })
  .limit(20);

// Insert
const { data: created } = await client.from('posts').insert({
  title: 'Hello',
  body:  'World',
}).select().single();

// Update
await client.from('posts')
  .update({ published: true })
  .eq('id', postId);

// Raw SQL (service_role only)
const { rows } = await admin.rpc('execute_sql', {
  sql: 'SELECT count(*) FROM posts WHERE published = true',
});

Authentication

typescript
// Create a user (server-side, service_role)
const { user } = await admin.auth.createUser({
  email:    'user@example.com',
  password: 'secret',
  user_metadata: { name: 'Jane' },
});

// Verify a user JWT from a request header
const { user } = await client.auth.verifyJwt(req.headers.authorization);

// Use user context for RLS-aware queries
const userClient = client.withAuth(accessToken);
const { data: ownPosts } = await userClient.from('posts').select('*');

Storage

typescript
import { readFileSync } from 'node:fs';

const buffer = readFileSync('./avatar.png');
const { path } = await client.storage
  .from('avatars')
  .upload(`${userId}/avatar.png`, buffer, { contentType: 'image/png' });

// Signed URL for a private file (expires in 1 hour)
const { url } = await client.storage
  .from('documents')
  .createSignedUrl('report.pdf', 3600);

Edge functions

typescript
const { data, error } = await client.functions.invoke('process-webhook', {
  body:    { event: 'payment.succeeded', amount: 5000 },
  headers: { 'x-idempotency-key': 'inv_123' },
});

Common patterns

Next.js API route

typescript
// app/api/posts/route.ts
import { createClient } from 'orbitnest-node';
import { cookies } from 'next/headers';

export async function GET() {
  const token = cookies().get('on-access-token')?.value;
  const client = createClient({
    projectUrl: process.env.ORBITNEST_URL!,
    anonKey:    process.env.ORBITNEST_ANON_KEY!,
  }).withAuth(token);

  const { data, error } = await client.from('posts').select('*');
  if (error) return Response.json({ error }, { status: 500 });
  return Response.json(data);
}

Serverless-friendly

The SDK uses fetch (no Node-specific deps) and has zero boot-time overhead. Great for Lambda, Vercel, Cloudflare Workers, Deno, Bun.

Error handling

All methods return a { data, error } tuple. Errors include a typed code, message, and optional details with PostgreSQL-specific info when relevant.

typescript
const { data, error } = await client.from('posts').insert({...});

if (error) {
  if (error.code === 'UNIQUE_VIOLATION') { /* handle */ }
  if (error.code === 'RLS_DENIED')       { /* handle */ }
  console.error(error.message, error.details);
}

Runtime support

  • Node 18+
  • Deno 1.38+
  • Bun 1.0+
  • Cloudflare Workers, Vercel Edge, AWS Lambda