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

@temboplus/afloat

v0.2.0-beta.6

Published

A foundational library for Temboplus-Afloat projects.

Readme

@temboplus/afloat

A foundational JavaScript/TypeScript library for TemboPlus-Afloat projects, providing abstracted server communication, shared utilities, and standardized data models for consistent development.

Key Features

  • Abstracted Server Communication

    • Simplifies front-end development by abstracting all interactions with the server behind model-specific repositories
    • Consuming projects only need to interact with these repositories, decoupling them from the underlying API implementation
  • Shared Utilities

    • Provides a collection of reusable helper functions for common tasks across Afloat projects, such as error handling
  • Data Models

    • Defines standardized data structures and interfaces for consistent data representation throughout the Afloat ecosystem
  • Enhanced Maintainability

    • Centralizes common logic, making it easier to maintain and update across all consuming projects
    • Reduces code duplication and improves consistency
  • Cross-Environment Compatibility

    • Works seamlessly in both client-side and server-side environments
    • Different patterns for client-side authentication management vs server-side token handling

Usage

Authentication Setup

Client-Side Usage

In client-side applications, use the AfloatAuth singleton for authentication management:

import { AfloatAuth } from "@temboplus/afloat";

// Initialize client auth (typically in your app entry point)
const auth = AfloatAuth.instance;

// Check if user is authenticated
console.log("User authenticated:", auth.isAuthenticated);

// Access current user
const user = auth.currentUser;
if (user) {
  console.log(`Logged in as: ${user.email}`);
}

// Login a user
try {
  const user = await auth.logIn("[email protected]", "password123");
  console.log("Login successful!");
} catch (error) {
  console.error("Login failed:", error.message);
}

// Check permissions
if (auth.checkPermission(Permission.ViewBalance)) {
  console.log("User can view balance");
}

// React hook for reactive user state
function UserProfile() {
  const user = auth.useCurrentUser();
  
  if (!user) {
    return <LoginForm />;
  }
  
  return <div>Hello, {user.name}!</div>;
}

Server-Side Usage

In server-side environments, do not use AfloatAuth. Instead, extract the authentication token from requests and pass it directly to repositories:

import { WalletRepository } from "@temboplus/afloat";

// In a server route handler or API endpoint
async function handleRequest(req, res) {
  try {
    // Extract token from request headers
    const token = req.headers.authorization?.replace('Bearer ', '');
    
    if (!token) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    // Create repository with explicit token
    const walletRepo = new WalletRepository({ token });
    
    // Use repository methods directly
    const balance = await walletRepo.getBalance({ wallet });
    const wallets = await walletRepo.getWallets();
    
    return res.json({ balance, wallets });
  } catch (error) {
    console.error('Server request error:', error);
    return res.status(500).json({ error: 'Internal server error' });
  }
}

Using Repositories

Repositories provide a consistent interface for data operations across environments.

Client-Side Repository Usage

import { WalletRepository } from "@temboplus/afloat";

// Option 1: Let repository use service locator (default behavior)
const walletRepo = new WalletRepository();

// Option 2: Explicitly pass token from auth manager
const auth = AfloatAuth.instance;
const walletRepo = new WalletRepository({ token: auth.getUserToken() });

// Use repository methods
async function displayBalance() {
  try {
    const balance = await walletRepo.getBalance({ wallet });
    console.log(`Current balance: ${balance.value} ${balance.currency}`);
  } catch (error) {
    console.error('Error fetching balance:', error);
  }
}

// Get all wallets
const wallets = await walletRepo.getWallets();

// Get wallet statement
const entries = await walletRepo.getStatement({ 
  wallet,
  range: {
    startDate: new Date('2024-01-01'),
    endDate: new Date('2024-01-31')
  }
});

Server-Side Repository Usage

import { WalletRepository } from "@temboplus/afloat";

async function processServerRequest(token: string) {
  // Create repository with explicit token (no auth manager needed)
  const walletRepo = new WalletRepository({ token });
  
  // Use repository methods directly
  const balance = await walletRepo.getBalance({ wallet });
  const wallets = await walletRepo.getWallets();
  
  return { balance, wallets };
}

// In Express.js middleware
app.use('/api/wallet', async (req, res, next) => {
  const token = extractTokenFromRequest(req);
  
  if (!token) {
    return res.status(401).json({ error: 'No token provided' });
  }
  
  req.walletRepo = new WalletRepository({ token });
  next();
});

Architecture Overview

Client-Side Pattern

  • Authentication Management: Use AfloatAuth.instance singleton
  • Repository Creation: Can use service locator or explicit token passing
  • State Management: Reactive updates through React hooks
  • Permission Checking: Built into the auth manager

Server-Side Pattern

  • No Auth Manager: Extract tokens directly from requests
  • Repository Creation: Always pass token explicitly
  • Stateless: Each request creates fresh repository instances
  • Permission Checking: Handle at route/middleware level

Best Practices

Client-Side Applications

  1. Initialize Early: Set up AfloatAuth.instance early in your application lifecycle
  2. Use React Hooks: Leverage auth.useCurrentUser() for reactive UI updates
  3. Handle Permissions: Check permissions before attempting restricted operations
  4. Error Handling: Implement proper error handling for authentication failures
// Good: Initialize auth early
const auth = AfloatAuth.instance;

// Good: Use reactive hooks in components
function Dashboard() {
  const user = auth.useCurrentUser();
  
  if (!user) return <LoginPrompt />;
  
  return <UserDashboard user={user} />;
}

// Good: Check permissions before operations
if (auth.checkPermission(Permission.ViewBalance)) {
  const repo = new WalletRepository();
  const balance = await repo.getBalance({ wallet });
}

Server-Side Applications

  1. Token Extraction: Always extract and validate tokens from requests
  2. Explicit Dependencies: Pass tokens explicitly to repositories
  3. Error Handling: Implement proper middleware for authentication errors
  4. Stateless Design: Create fresh repository instances per request
// Good: Extract token from request
const token = req.headers.authorization?.replace('Bearer ', '');

// Good: Explicit token passing
const repo = new WalletRepository({ token });

// Good: Middleware pattern
const authMiddleware = (req, res, next) => {
  const token = extractToken(req);
  
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  req.authToken = token;
  next();
};

// Good: Use in route handlers
app.get('/api/balance', authMiddleware, async (req, res) => {
  const repo = new WalletRepository({ token: req.authToken });
  const balance = await repo.getBalance({ wallet });
  res.json({ balance });
});

Testing

  1. Client-Side: Mock the AfloatAuth singleton or use dependency injection
  2. Server-Side: Mock repositories with test tokens
  3. Integration: Test both authentication flows and repository operations
// Client-side testing
const mockAuth = {
  currentUser: testUser,
  getUserToken: () => 'test-token',
  checkPermission: () => true
};

// Server-side testing  
const testRepo = new WalletRepository({ token: 'test-token' });

Troubleshooting

Common Issues

"Cannot find package 'react'" in Node.js

This error occurs when using Zustand v5. Ensure you're using Zustand v4:

npm install zustand@^4.5.7

Remove any existing v5 installation:

npm uninstall [email protected]

Authentication Errors in Server Environment

Problem: Trying to use AfloatAuth.instance in server-side code Solution: Extract tokens from requests and pass directly to repositories

// ❌ Don't do this in server code
const auth = AfloatAuth.instance; // This is client-side only!

// ✅ Do this instead
const token = req.headers.authorization?.replace('Bearer ', '');
const repo = new WalletRepository({ token });

Repository Token Issues

Problem: Repository calls failing with authentication errors Solution: Ensure tokens are properly extracted and passed

// ❌ Missing token
const repo = new WalletRepository(); // May fail in server context

// ✅ Explicit token
const repo = new WalletRepository({ token: extractedToken });

Debug Information

Use the auth manager's debug utilities for troubleshooting:

// Client-side debugging
const debugInfo = AfloatAuth.instance.getDebugInfo();
console.log('Auth Debug Info:', debugInfo);

API Reference

AfloatAuth (Client-Side Only)

  • AfloatAuth.instance - Singleton instance for client-side usage
  • currentUser - Get current authenticated user
  • isAuthenticated - Check authentication status
  • getUserToken() - Get current auth token
  • useCurrentUser() - React hook for reactive user state
  • checkPermission(perm) - Check user permissions
  • logIn(email, password) - Authenticate user
  • logOut() - Clear authentication state
  • resetPassword(current, new) - Update user password

Repository Pattern

All repositories accept optional configuration:

  • token - Authentication token for API calls
  • root - Custom API root URL

Example repositories:

  • WalletRepository - Wallet operations and balance management
  • AuthRepository - Authentication operations