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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@omx-sdk/core

v1.0.1

Published

Core module for OMX SDK with authentication and shared utilities

Readme

@omx-sdk/core

Core module for OMX SDK providing authentication, configuration, and shared utilities across all OMX services.

Features

  • 🔐 JWT Token Management - Automatic fetching and caching of JWT tokens from Supabase Edge Function
  • 🔄 Automatic Token Refresh - Handles token expiration and renewal seamlessly
  • 🚀 Authenticated API Requests - Built-in HTTP client with automatic token injection
  • 🛡️ Comprehensive Error Handling - Graceful handling of auth errors, network issues, and rate limiting
  • Caching & Performance - Intelligent token caching with configurable TTL
  • 🔧 TypeScript Support - Full type safety and IntelliSense support
  • 🌐 Retry Logic - Exponential backoff and configurable retry strategies
  • 🔒 Secure by Design - No sensitive Supabase credentials exposed to client

Installation

npm install @omx-sdk/core
# or
pnpm add @omx-sdk/core
# or
yarn add @omx-sdk/core

Quick Start

1. Supabase Edge Function Setup

Create a Supabase Edge Function at /functions/create-jwt-token/index.ts:

import { serve } from 'https://deno.land/[email protected]/http/server.ts';

serve(async (req) => {
  try {
    const { clientId, secretKey } = await req.json();

    // Validate credentials against your database
    const { data: business, error } = await supabaseClient
      .from('businesses')
      .select('*')
      .eq('client_id', clientId)
      .eq('secret_key', secretKey)
      .eq('is_active', true)
      .single();

    if (error || !business) {
      return new Response(
        JSON.stringify({ error: 'Invalid client credentials' }),
        { status: 401, headers: { 'Content-Type': 'application/json' } }
      );
    }

    // Generate JWT token
    const payload = {
      sub: business.id,
      business_id: business.id,
      client_id: business.client_id,
      iat: Math.floor(Date.now() / 1000),
      exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour
      iss: 'omx-auth',
      scope: business.permissions,
    };

    const token = await jwt.sign(payload, Deno.env.get('JWT_SECRET'));

    return new Response(
      JSON.stringify({
        token: token,
        token_type: 'Bearer',
        expires_in: 3600,
      }),
      { headers: { 'Content-Type': 'application/json' } }
    );
  } catch (error) {
    return new Response(JSON.stringify({ error: 'Internal server error' }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' },
    });
  }
});

2. Basic Usage

import { CoreAuth, AuthConfig } from '@omx-sdk/core';

// Configure authentication
const config: AuthConfig = {
  clientId: 'your-business-client-id',
  secretKey: 'your-business-secret-key',
  supabaseFnUrl:
    'https://your-project.supabase.co/functions/v1/create-jwt-token', // Optional: uses default if not provided
  tokenCacheTtl: 50 * 60 * 1000, // Cache for 50 minutes (optional)
};

// Initialize authentication
const auth = new CoreAuth(config);

// Get JWT token (automatically cached)
const token = await auth.getToken();

// Make authenticated API requests
const response = await auth.makeAuthenticatedRequest(
  'https://api.yourdomain.com/data',
  {
    method: 'GET',
  }
);

if (response.success) {
  console.log('Data:', response.data);
} else {
  console.error('Error:', response.error);
}

API Reference

CoreAuth Class

Constructor

new CoreAuth(config: AuthConfig)

Methods

getToken(forceRefresh?: boolean): Promise

Gets a valid JWT token, automatically handling caching and refresh.

// Get cached token (if valid)
const token = await auth.getToken();

// Force refresh token
const freshToken = await auth.getToken(true);
makeAuthenticatedRequest(url: string, options?: ApiRequestOptions): Promise<ApiResponse>

Makes an authenticated HTTP request with automatic token handling.

const response = await auth.makeAuthenticatedRequest('/api/users', {
  method: 'POST',
  body: { name: 'John Doe', email: '[email protected]' },
  timeout: 10000,
  retries: 3,
});
getTokenInfo(): TokenInfo

Returns information about the current cached token.

const info = auth.getTokenInfo();
console.log('Token valid:', info.isValid);
console.log('Expires at:', new Date(info.expiresAt));
clearToken(): void

Clears the cached token (useful for logout).

auth.clearToken();
updateConfig(updates: Partial): void

Updates the configuration and clears cached tokens.

auth.updateConfig({
  clientId: 'new-client-id',
  secretKey: 'new-secret-key',
});
dispose(): void

Cleans up resources and clears cache.

auth.dispose();

Configuration Options

interface AuthConfig {
  clientId: string; // Business client ID
  secretKey: string; // Business secret key
  supabaseFnUrl?: string; // Supabase Edge Function URL (optional - uses default production URL)
  tokenCacheTtl?: number; // Token cache TTL in ms (default: 55 minutes)
  maxRetries?: number; // Max retry attempts (default: 3)
  retryDelay?: number; // Retry delay in ms (default: 1000)
}

API Request Options

interface ApiRequestOptions {
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
  headers?: Record<string, string>;
  body?: any;
  timeout?: number; // Request timeout in ms
  retries?: number; // Override default retry count
}

Error Handling

The module provides comprehensive error handling with specific error types:

import {
  InvalidCredentialsError,
  TokenExpiredError,
  NetworkError,
  RateLimitError,
  ConfigurationError,
} from '@omx-sdk/core';

try {
  const response = await auth.makeAuthenticatedRequest('/api/data');
} catch (error) {
  if (error instanceof InvalidCredentialsError) {
    console.error('Invalid credentials:', error.message);
  } else if (error instanceof TokenExpiredError) {
    console.error('Token expired:', error.message);
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message);
  } else if (error instanceof RateLimitError) {
    console.error('Rate limited. Retry after:', error.details?.retryAfter);
  }
}

Examples

Example 1: Basic Token Management

import { CoreAuth } from '@omx-sdk/core';

const auth = new CoreAuth({
  clientId: 'business-123',
  secretKey: 'secret-456',
  supabaseFnUrl:
    'https://your-project.supabase.co/functions/v1/create-jwt-token', // Optional
});

// Get token
const token = await auth.getToken();

// Check token status
const tokenInfo = auth.getTokenInfo();
console.log('Token expires:', new Date(tokenInfo.expiresAt));

Example 2: Making API Requests

// GET request
const users = await auth.makeAuthenticatedRequest('/api/users');

// POST request with data
const newUser = await auth.makeAuthenticatedRequest('/api/users', {
  method: 'POST',
  body: {
    name: 'John Doe',
    email: '[email protected]',
  },
});

// PUT request with custom headers
const updated = await auth.makeAuthenticatedRequest('/api/users/123', {
  method: 'PUT',
  headers: {
    'X-Custom-Header': 'value',
  },
  body: { name: 'Jane Doe' },
});

Example 3: Error Handling

try {
  const response = await auth.makeAuthenticatedRequest('/api/protected');

  if (response.success) {
    console.log('Success:', response.data);
  } else {
    console.error('API Error:', response.error);
  }
} catch (error) {
  if (error instanceof NetworkError) {
    console.error('Network issue - retrying...');
    // Implement retry logic
  } else if (error instanceof RateLimitError) {
    const waitTime = error.details?.retryAfter || 60000;
    console.log(`Rate limited - waiting ${waitTime}ms`);
    // Wait and retry
  }
}

Advanced Usage

Custom Retry Logic

const response = await auth.makeAuthenticatedRequest('/api/critical-data', {
  method: 'POST',
  body: criticalData,
  timeout: 30000, // 30 second timeout
  retries: 5, // 5 retry attempts
});

Token Refresh Monitoring

// Monitor token status
setInterval(() => {
  const tokenInfo = auth.getTokenInfo();
  if (!tokenInfo.isValid) {
    console.log('Token expired, will refresh on next request');
  }
}, 60000); // Check every minute

Multiple Business Configurations

const businessAuth = new Map();

// Configure multiple businesses
const businesses = [
  { id: 'business1', clientId: 'client1', secretKey: 'secret1' },
  { id: 'business2', clientId: 'client2', secretKey: 'secret2' },
];

businesses.forEach((business) => {
  businessAuth.set(
    business.id,
    new CoreAuth({
      clientId: business.clientId,
      secretKey: business.secretKey,
      supabaseUrl: 'https://project.supabase.co',
      supabaseAnonKey: 'anon-key',
    })
  );
});

// Use specific business auth
const auth = businessAuth.get('business1');
const data = await auth.makeAuthenticatedRequest('/api/business-data');

Best Practices

  1. Edge Function Security: Use Supabase Edge Functions to keep sensitive database credentials secure
  2. Token Caching: Use appropriate cache TTL (default 55 minutes recommended)
  3. Error Handling: Always handle specific error types appropriately
  4. Resource Cleanup: Call dispose() when done to clean up resources
  5. Environment Configuration: Use different Edge Function URLs for dev/staging/production
  6. Rate Limiting: Implement proper backoff strategies for rate-limited APIs
  7. Monitoring: Log authentication failures and token refresh events

Security Features

  • 🔒 No Exposed Credentials: Supabase URL and keys are not exposed to client
  • 🛡️ Edge Function Isolation: Authentication logic runs in secure Supabase environment
  • 🔐 JWT Token Security: Short-lived tokens with automatic refresh
  • 🚫 No Client-Side Secrets: All sensitive operations happen server-side

Requirements

  • Node.js 16+ or modern browser environment
  • Supabase project with RPC function configured
  • TypeScript 4.5+ (for TypeScript projects)

License

MIT

Support

For issues and questions, please visit our GitHub repository.