JSPM

@bernierllc/supabase-client

1.0.3
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 31
  • Score
    100M100P100Q66138F
  • License SEE LICENSE IN LICENSE

Supabase client wrapper with Row Level Security, authentication integration, and type-safe queries

Package Exports

  • @bernierllc/supabase-client
  • @bernierllc/supabase-client/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@bernierllc/supabase-client) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@bernierllc/supabase-client

Supabase client wrapper with Row Level Security, authentication integration, retry logic, and type-safe queries.

Installation

npm install @bernierllc/supabase-client

Features

  • Supabase Client Wrapper - Clean API around Supabase JavaScript SDK
  • Retry Logic - Automatic retry for transient failures using @bernierllc/retry-policy
  • Structured Error Handling - Consistent SupabaseResult interface for all operations
  • Logger Integration - Built-in logging with @bernierllc/logger
  • Type Safety - Full TypeScript support with strict typing
  • CRUD Operations - Query, insert, update, delete with filters
  • RPC Support - Call Supabase RPC functions
  • Storage Operations - Upload, download, and manage files
  • Auth Operations - Sign in, sign up, sign out, session management
  • Query Builder - Flexible query building with filters, ordering, pagination

Usage

Basic Setup

import { SupabaseClient } from '@bernierllc/supabase-client';

const client = new SupabaseClient({
  url: process.env.SUPABASE_URL!,
  anonKey: process.env.SUPABASE_ANON_KEY!,
  enableRetry: true,
  maxRetries: 3,
  debug: false,
});

Query Data

// Simple query
const result = await client.query('users', {
  select: '*',
  limit: 10,
});

if (result.success) {
  console.log('Users:', result.data);
  console.log('Count:', result.count);
} else {
  console.error('Error:', result.error);
}

// Query with filters
const activeUsers = await client.query('users', {
  select: 'id, name, email',
  filters: [
    { column: 'status', operator: 'eq', value: 'active' },
    { column: 'created_at', operator: 'gt', value: '2024-01-01' },
  ],
  orderBy: { column: 'created_at', ascending: false },
  limit: 20,
  offset: 0,
});

// Get single record
const user = await client.query('users', {
  filters: [{ column: 'id', operator: 'eq', value: 123 }],
  single: true,
});

Insert Data

// Insert single record
const result = await client.insert('users', {
  name: 'John Doe',
  email: 'john@example.com',
  status: 'active',
});

if (result.success) {
  console.log('Inserted:', result.data);
}

// Insert multiple records
const bulkResult = await client.insert('users', [
  { name: 'User 1', email: 'user1@example.com' },
  { name: 'User 2', email: 'user2@example.com' },
]);

// Upsert (insert or update)
const upsertResult = await client.insert(
  'users',
  { id: 123, name: 'Updated Name' },
  { upsert: true }
);

Update Data

const result = await client.update(
  'users',
  { status: 'inactive', updated_at: new Date().toISOString() },
  [{ column: 'id', operator: 'eq', value: 123 }]
);

if (result.success) {
  console.log('Updated:', result.data);
}

Delete Data

const result = await client.delete('users', [
  { column: 'status', operator: 'eq', value: 'deleted' },
]);

if (result.success) {
  console.log('Deleted:', result.data);
}

RPC Functions

const result = await client.rpc('calculate_user_stats', {
  params: {
    user_id: 123,
    start_date: '2024-01-01',
  },
});

if (result.success) {
  console.log('Stats:', result.data);
}

Storage Operations

// Upload file
const file = new File(['content'], 'document.pdf', { type: 'application/pdf' });
const uploadResult = await client.storageUpload('documents', 'user123/document.pdf', file, {
  contentType: 'application/pdf',
  cacheControl: '3600',
  upsert: false,
});

if (uploadResult.success) {
  console.log('Uploaded to:', uploadResult.data?.path);
}

// Download file
const downloadResult = await client.storageDownload('documents', 'user123/document.pdf');

if (downloadResult.success) {
  const blob = downloadResult.data;
  // Use blob...
}

// Get public URL
const urlResult = client.getStoragePublicUrl('avatars', 'user123/avatar.jpg');

if (urlResult.success) {
  console.log('Public URL:', urlResult.data);
}

Auth Operations

// Sign in
const signInResult = await client.authSignIn({
  email: 'user@example.com',
  password: 'password123',
});

if (signInResult.success) {
  console.log('User:', signInResult.data?.user);
  console.log('Session:', signInResult.data?.session);
}

// Sign up
const signUpResult = await client.authSignUp({
  email: 'newuser@example.com',
  password: 'password123',
  options: {
    data: { name: 'New User' },
    emailRedirectTo: 'https://app.example.com/welcome',
  },
});

// Sign out
await client.authSignOut();

// Get current session
const sessionResult = await client.authGetSession();

if (sessionResult.success && sessionResult.data?.session) {
  console.log('Active session:', sessionResult.data.session);
}

Advanced Usage

// Access underlying Supabase client for advanced features
const supabaseClient = client.getClient();

// Use Supabase realtime subscriptions
const channel = supabaseClient
  .channel('users-changes')
  .on('postgres_changes', { event: '*', schema: 'public', table: 'users' }, (payload) => {
    console.log('Change received!', payload);
  })
  .subscribe();

Configuration

SupabaseClientConfig

interface SupabaseClientConfig {
  /** Supabase project URL */
  url: string;
  /** Supabase anonymous key */
  anonKey: string;
  /** Service role key (optional, for admin operations) */
  serviceRoleKey?: string;
  /** Enable retry logic for transient failures (default: true) */
  enableRetry?: boolean;
  /** Maximum number of retry attempts (default: 3) */
  maxRetries?: number;
  /** Enable debug logging (default: false) */
  debug?: boolean;
}

Filter Operators

type FilterOperator =
  | 'eq'      // equals
  | 'neq'     // not equals
  | 'gt'      // greater than
  | 'gte'     // greater than or equal
  | 'lt'      // less than
  | 'lte'     // less than or equal
  | 'like'    // pattern match (case-sensitive)
  | 'ilike'   // pattern match (case-insensitive)
  | 'in'      // in array
  | 'is';     // is null/not null

API Reference

Query Operations

  • query<T>(table: string, options?: QueryOptions): Promise<SupabaseResult<T[]>>

Insert Operations

  • insert<T>(table: string, data: Partial<T> | Partial<T>[], options?: InsertOptions): Promise<SupabaseResult<T[]>>

Update Operations

  • update<T>(table: string, data: Partial<T>, filters: QueryFilter[], options?: UpdateOptions): Promise<SupabaseResult<T[]>>

Delete Operations

  • delete<T>(table: string, filters: QueryFilter[], options?: DeleteOptions): Promise<SupabaseResult<T[]>>

RPC Operations

  • rpc<T>(functionName: string, options?: RPCOptions): Promise<SupabaseResult<T>>

Storage Operations

  • storageUpload(bucket: string, path: string, file: File | Blob | Buffer, options?: StorageUploadOptions): Promise<SupabaseResult<{ path: string }>>
  • storageDownload(bucket: string, path: string, options?: StorageDownloadOptions): Promise<SupabaseResult<Blob>>
  • getStoragePublicUrl(bucket: string, path: string): SupabaseResult<string>

Auth Operations

  • authSignIn(options: AuthSignInOptions): Promise<SupabaseResult<{ user: unknown; session: unknown }>>
  • authSignUp(options: AuthSignUpOptions): Promise<SupabaseResult<{ user: unknown; session: unknown }>>
  • authSignOut(): Promise<SupabaseResult<void>>
  • authGetSession(): Promise<SupabaseResult<{ session: unknown }>>

Utility

  • getClient(): SupabaseClient - Get underlying Supabase client for advanced usage

Error Handling

All methods return a SupabaseResult<T> with consistent structure:

interface SupabaseResult<T = unknown> {
  success: boolean;
  data?: T;
  error?: string;
  count?: number;
}

Always check success before accessing data:

const result = await client.query('users');

if (result.success) {
  // Safe to access result.data
  console.log(result.data);
} else {
  // Handle error
  console.error(result.error);
}

Retry Logic

The client automatically retries transient failures using exponential backoff:

  • Initial delay: 1000ms
  • Max delay: 10000ms
  • Jitter: enabled
  • Default max retries: 3

Disable retry for specific operations:

const client = new SupabaseClient({
  url: process.env.SUPABASE_URL!,
  anonKey: process.env.SUPABASE_ANON_KEY!,
  enableRetry: false, // Disable retry
});

Integration Status

Logger Integration

Status: Integrated

Justification: This package uses @bernierllc/logger for structured logging of all database operations. Logs include query execution, authentication events, retry attempts, and error details to help with debugging and monitoring.

Pattern: Direct integration - logger is a required dependency for this package.

NeverHub Integration

Status: Not applicable

Justification: This is a core database client package that provides Supabase connectivity. It does not participate in service discovery, event publishing, or service mesh operations. Database clients are infrastructure utilities that don't require service registration or discovery.

Pattern: Core utility - no service mesh integration needed. Service-level packages that use this client can integrate with NeverHub if needed.

Docs-Suite Integration

Status: Ready

Format: TypeDoc-compatible JSDoc comments are included throughout the source code. All public APIs are documented with examples and type information.

Dependencies

  • @supabase/supabase-js - Official Supabase JavaScript client
  • @bernierllc/logger - Structured logging
  • @bernierllc/retry-policy - Retry logic and backoff calculation

Testing

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests once (no watch)
npm run test:run

Building

# Build TypeScript
npm run build

# Clean build artifacts
npm run clean

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

See Also