npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@e-techsolutions/e-baas-sdk

v1.3.0

Published

Official E-BaaS TypeScript SDK - Backend as a Service client library

Readme

E-BaaS SDK

The official TypeScript SDK for E-BaaS (Enterprise Backend as a Service) - A comprehensive backend-as-a-service platform.

Installation

npm install @e-techsolutions/e-baas-sdk@latest
# or
yarn add @e-techsolutions/e-baas-sdk@latest

Quick Start

import { createClient } from "@e-techsolutions/e-baas-sdk";

// Basic configuration (required)
const EBAAS_URL = process.env.EBAAS_API_URL; // required - https://your-api-e-baas-service
const EBAAS_KEY = process.env.EBAAS_API_KEY; // required - your API key
const WORKSPACE_ID = process.env.EBAAS_WORKSPACE_ID; // required - your workspace ID

export const ebaas = createClient(EBAAS_URL, EBAAS_KEY, {
  // Database configuration (required)
  database: {
    workspaceId: WORKSPACE_ID, // required
    autoDetectCustomDatabase: true, // optional (default: false)
  },
  // Other configurations are optional
});

Complete Authentication Flow

// 1. User login
const { user, session, error } = await ebaas.auth.signIn({
  email: "[email protected]",
  password: "secure-password",
});

if (error) {
  console.error("Login failed:", error);
  return;
}

// 2. Configure session in SDK (REQUIRED!)
ebaas.auth.setSession(session);

// 3. Persist session (optional)
localStorage.setItem("ebaas_session", JSON.stringify(session));
localStorage.setItem("ebaas_user", JSON.stringify(user));

// 4. Now you can use database operations normally
const query = ebaas.from("users").select("*");
const { data, error } = await query.execute();

if (error) {
  console.error("Error fetching users:", error);
} else {
  console.log("Users found:", data.length);
}

Session Restoration

// Restore session on app initialization
const restoreSession = () => {
  const savedSession = localStorage.getItem("ebaas_session");
  const savedUser = localStorage.getItem("ebaas_user");

  if (savedSession && savedUser) {
    const sessionData = JSON.parse(savedSession);

    // Check if not expired
    if (sessionData.expires_at > Date.now()) {
      // Restore session in SDK
      ebaas.auth.setSession(sessionData);
      console.log("✅ Session restored automatically");
    } else {
      // Clear expired session
      localStorage.removeItem("ebaas_session");
      localStorage.removeItem("ebaas_user");
    }
  }
};

Environment Variables

Create a .env file in your project root:

EBAAS_API_URL=https://your-api-e-baas-service
EBAAS_API_KEY=your-api-key-here
EBAAS_WORKSPACE_ID=your-workspace-id-here

Note: This works with any bundler (Webpack, Vite, Next.js, etc.) that supports process.env.

Features

  • Authentication - Email/password and OAuth providers (Google, GitHub, Facebook)
  • Database - PostgreSQL with real-time subscriptions and RPC support
  • Custom Database - Use your own PostgreSQL database with automatic detection
  • Storage - File uploads with CDN integration and image transformations
  • Realtime - WebSocket subscriptions for live data updates
  • Edge Functions - Serverless functions with dual runtime (Node.js VM + Deno) and native SDK integration
  • TypeScript - Full type safety and IntelliSense support

Usage Examples

Authentication

// Sign up with email/password
const { user, session, error } = await ebaas.auth.signUp({
  email: "[email protected]",
  password: "secure-password",
  name: "John Doe",
});

// Sign in
const { user, session, error } = await ebaas.auth.signIn({
  email: "[email protected]",
  password: "secure-password",
});

// Get current user
const user = await ebaas.auth.getUser();

// Sign out
await ebaas.auth.signOut();

⚠️ IMPORTANT - Session Configuration:

After login, you MUST configure the session in the SDK for all subsequent operations to work correctly:

// Complete authentication flow
const loginUser = async () => {
  // 1. Perform login
  const { user, session, error } = await ebaas.auth.signIn({
    email: "[email protected]",
    password: "secure-password",
  });

  if (error) {
    console.error("Login failed:", error);
    return;
  }

  // 2. Configure session in SDK (MANDATORY STEP!)
  ebaas.auth.setSession(session);

  // 3. Persist session in localStorage (optional)
  localStorage.setItem("ebaas_session", JSON.stringify(session));
  localStorage.setItem("ebaas_user", JSON.stringify(user));

  console.log("✅ Login and session configuration completed");
};

// Restore session on application initialization
const restoreSession = () => {
  const savedSession = localStorage.getItem("ebaas_session");
  const savedUser = localStorage.getItem("ebaas_user");

  if (savedSession && savedUser) {
    const sessionData = JSON.parse(savedSession);

    // Check if not expired
    if (sessionData.expires_at > Date.now()) {
      // Restore session in SDK
      ebaas.auth.setSession(sessionData);
      console.log("✅ Session restored automatically");
    } else {
      // Clear expired session
      localStorage.removeItem("ebaas_session");
      localStorage.removeItem("ebaas_user");
    }
  }
};

Database Operations

// Select data
const query = ebaas.from("users").select("*");
const { data, error } = await query.execute();

if (error) {
  console.error("Error fetching users:", error);
} else {
  console.log("Users found:", data.length);
}

// Select specific fields for better performance
const query = ebaas
  .from("users")
  .select("id, name, email")
  .eq("status", "active")
  .order("created_at", { ascending: false })
  .limit(10);
const { data, error } = await query.execute();

// Insert data
const query = ebaas.from("users").insert({
  name: "John Doe",
  email: "[email protected]",
});
const { data, error } = await query.execute();

if (error) {
  console.error("Error creating user:", error);
} else {
  console.log("User created successfully:", data);
}

// Update data
const query = ebaas.from("users").update({ name: "John Smith" }).eq("id", 123);
const { data, error } = await query.execute();

if (error) {
  console.error("Error updating user:", error);
} else {
  console.log("User updated successfully:", data);
}

// Delete data
const query = ebaas.from("users").delete().eq("id", 123);
const { data, error } = await query.execute();

if (error) {
  console.error("Error deleting user:", error);
} else {
  console.log("User deleted successfully");
}

// RPC (stored procedures)
const query = ebaas.rpc("get_user_stats", {
  user_id: 123,
});
const { data, error } = await query.execute();

Advanced Filtering & Query Operators

The E-BaaS SDK supports PostgREST-style operators for powerful filtering capabilities:

Comparison Operators

// Equality
const users = await ebaas.from("users")
  .select("*")
  .eq("status", "active")  // status = 'active'
  .execute();

// Not equal
const users = await ebaas.from("users")
  .select("*")
  .neq("status", "deleted")  // status != 'deleted'
  .execute();

// Greater than
const users = await ebaas.from("users")
  .select("*")
  .gt("age", 18)  // age > 18
  .execute();

// Greater than or equal
const users = await ebaas.from("users")
  .select("*")
  .gte("created_at", "2024-01-01")  // created_at >= '2024-01-01'
  .execute();

// Less than
const users = await ebaas.from("users")
  .select("*")
  .lt("age", 65)  // age < 65
  .execute();

// Less than or equal
const users = await ebaas.from("users")
  .select("*")
  .lte("updated_at", "2024-12-31")  // updated_at <= '2024-12-31'
  .execute();

Text Search Operators

// Case-sensitive pattern matching
const users = await ebaas.from("users")
  .select("*")
  .like("name", "%John%")  // name LIKE '%John%'
  .execute();

// Case-insensitive pattern matching
const users = await ebaas.from("users")
  .select("*")
  .ilike("email", "%@gmail.com")  // email ILIKE '%@gmail.com'
  .execute();

Null Checks

// Check for null values
const users = await ebaas.from("users")
  .select("*")
  .is("deleted_at", null)  // deleted_at IS NULL
  .execute();

Multiple Filters on Same Field

NEW: You can now apply multiple filters to the same field for range queries:

// Date range filtering (multiple filters on same field)
const expenses = await ebaas.from("expenses")
  .select("id, user_id, description, amount, due_date")
  .eq("user_id", "7a79cc66-140e-41e0-9bde-ba51e338adac")
  .gte("due_date", "2025-11-01")  // due_date >= '2025-11-01'
  .lt("due_date", "2025-12-01")   // due_date < '2025-12-01'
  .order("due_date", { ascending: true })
  .execute();

// Numeric range filtering
const products = await ebaas.from("products")
  .select("*")
  .gte("price", 100)    // price >= 100
  .lte("price", 500)    // price <= 500
  .execute();

// Age range
const users = await ebaas.from("users")
  .select("*")
  .gt("age", 18)        // age > 18
  .lt("age", 65)        // age < 65
  .execute();

Combining Multiple Filters

// Multiple conditions (AND logic)
const activeUsers = await ebaas.from("users")
  .select("id, name, email, status, created_at")
  .eq("status", "active")
  .gte("created_at", "2024-01-01")
  .ilike("email", "%@company.com")
  .order("created_at", { ascending: false })
  .limit(50)
  .execute();

// Complex date and status filtering
const recentExpenses = await ebaas.from("expenses")
  .select("*")
  .eq("status", "pending")
  .gte("due_date", "2025-11-01")
  .lt("due_date", "2025-12-01")
  .gt("amount", 0)
  .order("due_date", { ascending: true })
  .execute();

Ordering and Pagination

// Single column ordering
const users = await ebaas.from("users")
  .select("*")
  .order("created_at", { ascending: false })  // ORDER BY created_at DESC
  .execute();

// Multiple column ordering
const expenses = await ebaas.from("expenses")
  .select("*")
  .order("due_date", { ascending: true })
  .order("created_at", { ascending: false })  // Secondary sort
  .execute();

// Pagination
const users = await ebaas.from("users")
  .select("*")
  .order("id", { ascending: true })
  .range(0, 9)    // LIMIT 10 OFFSET 0 (first 10 records)
  .execute();

const nextPage = await ebaas.from("users")
  .select("*")
  .order("id", { ascending: true })
  .range(10, 19)  // LIMIT 10 OFFSET 10 (next 10 records)
  .execute();

Performance Tips

// Select only needed columns for better performance
const users = await ebaas.from("users")
  .select("id, name, email")  // Instead of select("*")
  .eq("status", "active")
  .limit(100)
  .execute();

// Use indexes for filtering - ensure your database has indexes on:
// - Frequently filtered columns (status, user_id, etc.)
// - Date columns used in range queries (created_at, due_date, etc.)
// - Foreign keys (user_id, category_id, etc.)

Query Builder Pattern

// Build queries conditionally
let query = ebaas.from("expenses")
  .select("id, description, amount, due_date, status");

// Add filters conditionally
if (userId) {
  query = query.eq("user_id", userId);
}

if (startDate) {
  query = query.gte("due_date", startDate);
}

if (endDate) {
  query = query.lt("due_date", endDate);
}

if (status) {
  query = query.eq("status", status);
}

// Execute the final query
const { data, error } = await query
  .order("due_date", { ascending: true })
  .limit(100)
  .execute();

Raw SQL Queries

For complex queries beyond the query builder, use RPC functions:

// Create a stored procedure for complex filtering
const query = ebaas.rpc("get_expenses_by_date_range", {
  p_user_id: "7a79cc66-140e-41e0-9bde-ba51e338adac",
  p_start_date: "2025-11-01",
  p_end_date: "2025-12-01",
  p_status: "pending"
});
const { data, error } = await query.execute();

Custom Database

// Configure with automatic custom database detection
const ebaas = createClient(EBAAS_URL, EBAAS_KEY, {
  database: {
    workspaceId: WORKSPACE_ID,
    autoDetectCustomDatabase: true, // Enable custom database auto-detection
  },
});

Storage

// Upload file
const { data, error } = await ebaas.storage.from("avatars").upload("user-123.jpg", file, {
  cacheControl: "3600",
  upsert: true,
});

// Download file
const { data, error } = await ebaas.storage.from("avatars").download("user-123.jpg");

// Get public URL
const { data } = ebaas.storage.from("avatars").getPublicUrl("user-123.jpg");

// Get signed URL (for private files)
const { data, error } = await ebaas.storage.from("private-docs").createSignedUrl("document.pdf", 60); // 60 seconds

// List files
const { data, error } = await ebaas.storage.from("avatars").list("", {
  limit: 100,
  offset: 0,
  sortBy: { column: "name", order: "asc" },
});

Realtime Subscriptions

// Subscribe to database changes
const channel = ebaas.channel("realtime:users");

channel.onPostgresChanges(
  {
    event: "*", // INSERT, UPDATE, DELETE, or *
    schema: "public",
    table: "users",
  },
  (payload) => {
    console.log("Change received!", payload);
  }
);

channel.subscribe();

// Broadcast messages
channel.send({
  type: "broadcast",
  event: "message",
  payload: { text: "Hello World!" },
});

// Presence tracking
channel.track({ user_id: 123, status: "online" });

// Unsubscribe
channel.unsubscribe();

Edge Functions

Client-side Function Invocation

// Invoke authenticated function (requires session)
const { data, error } = await ebaas.functions.invoke("hello-world", {
  body: { name: "John" },
  headers: { "Content-Type": "application/json" },
});

// Invoke public function (no authentication required)
const response = await fetch("https://your-api-domain.com/functions/v1/public/hello-world", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "John" }),
});
const data = await response.json();

// List functions
const { data, error } = await ebaas.functions.list();

// Get function details
const { data, error } = await ebaas.functions.get("hello-world");

Native SDK Integration in Edge Functions

The SDK is natively available within Edge Functions with global methods:

// Edge Function with native SDK access
const users = await from("users").select("*").limit(10);
const bucket = bucket("uploads");
await channel("notifications").send("user_created", { user: userData });
return createResponse({ success: true, users });

Available globals: from(), rpc(), bucket(), channel(), invoke(), ebaas.*

Advanced Configuration

const ebaas = createClient(
  "https://your-api-domain.com", // required - API URL
  "your-api-key", // required - API Key
  {
    // Database configuration (required)
    database: {
      workspaceId: "your-workspace-id", // required - Workspace ID
      autoDetectCustomDatabase: true, // optional (default: false)
    },
    // Authentication configuration (optional)
    auth: {
      autoRefreshToken: true, // optional (default: true)
      persistSession: true, // optional (default: true)
      detectSessionInUrl: true, // optional (default: true)
    },
    // Realtime configuration (optional)
    realtime: {
      params: {
        eventsPerSecond: 10, // optional (default: 10)
      },
    },
    // Global configuration (optional)
    global: {
      headers: {
        "x-custom-header": "custom-value", // optional - custom headers
      },
    },
  }
);

Error Handling

import { EBaaSError } from "@e-techsolutions/e-baas-sdk";

try {
  const query = ebaas.from("users").select("*");
  const { data, error } = await query.execute();
} catch (error) {
  if (error instanceof EBaaSError) {
    console.error("E-BaaS Error:", error.message);
    console.error("Status:", error.status);
    console.error("Details:", error.details);
  }
}

Secure DELETE Operations

Security Validation

E-BaaS implements strict validation for DELETE and UPDATE operations, requiring at least one filter to prevent accidental mass deletions:

// ✅ CORRECT: DELETE with specific filter
const query = ebaas.from("users").delete().eq("id", 123);
const { data, error } = await query.execute();

// ❌ ERROR: DELETE without filters (returns "Security violation")
const query = ebaas.from("users").delete();
const { data, error } = await query.execute(); // Fails with security error

Secure DELETE Operations with Required Filters

Always use the SDK with proper filters for safe DELETE operations:

// DELETE using SDK with required filter
const query = ebaas.from("users").delete().eq("id", userId);
const { data, error } = await query.execute();

if (error) {
  console.error("Error deleting user:", error);
} else {
  console.log("User deleted successfully");
}

Refresh Token Management

Automatic Token Refresh (Default)

The E-BaaS SDK automatically manages refresh tokens for workspace users, ensuring seamless authentication without manual intervention:

const ebaas = createClient(EBAAS_URL, EBAAS_KEY, {
  database: {
    workspaceId: WORKSPACE_ID,
  },
  auth: {
    autoRefreshToken: true, // Default: true - automatic refresh enabled
    persistSession: true,   // Default: true - session persistence
  },
});

How Automatic Refresh Works

  1. Login Phase: When a user logs in, they receive both an access token and a refresh token
  2. Background Monitoring: The SDK monitors token expiration automatically
  3. Seamless Refresh: Before expiration, the SDK calls /auth/v1/sdk/refresh to get new tokens
  4. Token Rotation: Old refresh tokens are invalidated for security (refresh token rotation)
  5. Continued Operation: All database operations continue without interruption

Manual Refresh Token Management

For advanced use cases, you can disable automatic refresh and manage tokens manually:

const ebaas = createClient(EBAAS_URL, EBAAS_KEY, {
  database: {
    workspaceId: WORKSPACE_ID,
  },
  auth: {
    autoRefreshToken: false, // Disable automatic refresh
  },
});

// Manual refresh when needed
const refreshTokens = async () => {
  try {
    const query = ebaas.auth.refreshSession();
    const { data, error } = await query.execute();
    
    if (error) {
      console.error('Failed to refresh token:', error);
      // Redirect to login page
      return;
    }
    
    // Update session in SDK
    ebaas.auth.setSession(data.session);
    
    // Update localStorage
    localStorage.setItem('ebaas_session', JSON.stringify(data.session));
    
    console.log('✅ Tokens refreshed successfully');
  } catch (error) {
    console.error('Token refresh error:', error);
    // Handle refresh failure - redirect to login
  }
};

React Hook for Token Management

Here's a custom React hook for handling token refresh and expiration:

import { useEffect, useCallback } from 'react';
import { ebaas } from './ebaas-client';

export const useTokenRefresh = () => {
  const checkTokenExpiration = useCallback(async () => {
    const session = ebaas.auth.getSession();
    
    if (!session?.expires_at) return;
    
    const expiresAt = new Date(session.expires_at);
    const now = new Date();
    const timeToExpiry = expiresAt.getTime() - now.getTime();
    
    // Refresh if token expires in less than 5 minutes
    if (timeToExpiry < 5 * 60 * 1000) {
      try {
        const query = ebaas.auth.refreshSession();
        const { data, error } = await query.execute();
        
        if (error) {
          console.error('Token refresh failed:', error);
          // Redirect to login
          window.location.href = '/login';
          return;
        }
        
        // Update session
        ebaas.auth.setSession(data.session);
        localStorage.setItem('ebaas_session', JSON.stringify(data.session));
        
        console.log('✅ Token refreshed proactively');
      } catch (error) {
        console.error('Token refresh error:', error);
        // Handle error - redirect to login
        window.location.href = '/login';
      }
    }
  }, []);
  
  useEffect(() => {
    // Check immediately
    checkTokenExpiration();
    
    // Check every 2 minutes
    const interval = setInterval(checkTokenExpiration, 2 * 60 * 1000);
    
    return () => clearInterval(interval);
  }, [checkTokenExpiration]);
};

// Usage in your main App component
const App = () => {
  useTokenRefresh(); // Add this hook to your main App
  
  return (
    <div>
      {/* Your app content */}
    </div>
  );
};

Token Refresh Error Handling

const handleDatabaseOperation = async () => {
  try {
    const query = ebaas.from('users').select('*');
    const { data, error } = await query.execute();
    
    if (error) {
      // Check if error is due to token expiration
      if (error.status === 401 || error.message?.includes('token')) {
        console.log('Token expired, attempting refresh...');
        
        const { session, error } = await ebaas.auth.refreshSession();
        
        if (error) {
          // Refresh failed - redirect to login
          console.error('Token refresh failed:', error);
          window.location.href = '/login';
          return;
        }
        
        // Update session and retry operation
        ebaas.auth.setSession(session);
        const { data, error } = await query.execute();
        
        if (!error) {
          console.log('✅ Operation successful after token refresh');
          return data;
        }
      }
      
      console.error('Database operation failed:', error);
    }
    
    return data;
  } catch (error) {
    console.error('Unexpected error:', error);
  }
};

Security Benefits

  • Token Rotation: Each refresh generates new tokens and invalidates old ones
  • Short-lived Access Tokens: Access tokens have shorter lifespans for security
  • Automatic Cleanup: Expired and revoked tokens are automatically cleaned up
  • Session Tracking: Each session is tracked with IP address and user agent
  • Workspace Isolation: Refresh tokens are isolated per workspace for multi-tenancy

Configuration Options

const ebaas = createClient(EBAAS_URL, EBAAS_KEY, {
  auth: {
    autoRefreshToken: true,    // Enable/disable automatic refresh
    persistSession: true,      // Persist session in localStorage
    detectSessionInUrl: true,  // Detect session from URL params
  },
});

TypeScript Support

The SDK is built with TypeScript and provides full type safety:

interface User {
  id: number;
  name: string;
  email: string;
  created_at: string;
}

const query = ebaas.from<User>("users").select("*");
const { data, error } = await query.execute();

// data is now typed as User[] | null

Edge Functions Runtime Support

Enhanced Edge Functions with dual runtime support (Node.js VM + Deno) and native SDK integration.

License

MIT