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

@pineliner/common-services

v1.0.5

Published

Shared server-side Express components and utilities for fulfilment system APIs

Readme

@fulfilment/common-services

Shared components and utilities for the fulfilment system, supporting both server-side (Express APIs) and client-side (frontend applications) usage.

Installation

bun add @fulfilment/common-services

Features

Server-Side

  • Authentication Middleware - JWT-based authentication with configurable options
  • CORS Middleware - Standardized CORS configuration with presets
  • Error Handling - Centralized error handling middleware
  • Health Checks - Standardized health check endpoints
  • Express App Factory - Pre-configured Express app setup

Client-Side

  • API Client - Type-safe HTTP client with authentication support
  • Auth Client - Token management and user profile handling
  • Utilities - URL building, retry logic, pagination helpers
  • Local Storage - Browser storage and cookie utilities

Common

  • TypeScript Support - Full type definitions for both server and client
  • Shared Types - Common interfaces and types across server/client

Usage

Server-Side Usage

Quick Start - Full App Factory

import { createFullApp } from '@fulfilment/common-services';

const app = createFullApp({
  cors: {
    origins: ['http://localhost:3000', 'http://localhost:3001'],
    credentials: true
  },
  auth: {
    jwtSecret: process.env.JWT_SECRET,
    skipPaths: ['/health', '/docs']
  },
  health: {
    serviceName: 'my-api',
    version: '1.0.0'
  }
});

// Your protected routes
app.use('/api/users', (app as any).auth, userRoutes);

app.listen(3000);

Individual Middleware Usage

Authentication

import { createAuthMiddleware, AuthMiddleware } from '@fulfilment/common-services/middleware';

// Simple usage
const auth = createAuthMiddleware({
  jwtSecret: process.env.JWT_SECRET,
  expiresIn: '24h',
  skipPaths: ['/health', '/docs']
});

app.use('/api', auth, apiRoutes);

// Class-based usage for token generation
const authManager = new AuthMiddleware({
  jwtSecret: process.env.JWT_SECRET
});

const token = authManager.generateToken({
  userId: '123',
  email: '[email protected]'
});

CORS

import { createCorsMiddleware, corsConfigs } from '@fulfilment/common-services/middleware';

// Development preset
app.use(createCorsMiddleware(corsConfigs.development));

// Custom configuration  
app.use(createCorsMiddleware({
  origins: ['https://myapp.com'],
  methods: ['GET', 'POST'],
  credentials: false
}));

Error Handling

import { createErrorHandler, notFoundHandler } from '@fulfilment/common-services/middleware';

// 404 handler
app.use(notFoundHandler);

// Error handler
app.use(createErrorHandler({
  includeStack: process.env.NODE_ENV === 'development',
  logErrors: true,
  customLogger: (error, req) => {
    console.error('API Error:', error.message, req.path);
  }
}));

Health Checks

import { createHealthEndpoint } from '@fulfilment/common-services/utils';

const healthCheck = createHealthEndpoint({
  serviceName: 'pipeline-api',
  version: '1.0.0',
  customChecks: [
    async () => ({
      name: 'database',
      status: 'ok', // or 'error'
      details: { connectionCount: 5 }
    })
  ]
});

app.get('/health', healthCheck);

Manual App Setup

import express from 'express';
import { 
  createCorsMiddleware, 
  createAuthMiddleware,
  createErrorHandler,
  notFoundHandler 
} from '@fulfilment/common-services';

const app = express();

// Basic middleware
app.use(express.json());
app.use(createCorsMiddleware());

// Health check (before auth)
app.get('/health', simpleHealthCheck);

// Authentication for API routes
const auth = createAuthMiddleware();
app.use('/api', auth, apiRoutes);

// Error handling
app.use(notFoundHandler);
app.use(createErrorHandler());

Type Definitions

import type { 
  JWTPayload, 
  AuthenticatedRequest, 
  HealthCheckResponse,
  CORSConfig 
} from '@fulfilment/common-services';

// Extend Express Request with auth info
declare global {
  namespace Express {
    interface Request {
      user?: JWTPayload;
      tenantId?: string;
    }
  }
}

Migration from Existing Code

To migrate existing API packages:

  1. Install the common-services package
  2. Replace auth middleware - Remove local auth.ts files and use the shared version
  3. Replace CORS setup - Use the shared CORS configuration
  4. Replace error handlers - Use the shared error handling middleware
  5. Replace health checks - Use the shared health check utilities
  6. Update imports - Replace local imports with package imports

Configuration

All middleware accepts configuration objects to customize behavior:

  • AuthConfig - JWT secret, expiration, skip paths
  • CORSConfig - Origins, headers, methods, credentials
  • ErrorHandlerConfig - Stack traces, logging, custom logger
  • HealthCheckConfig - Service name, version, custom checks

Client-Side Usage

Import Options

// Option 1: Import from specific client module
import { ApiClient, AuthClient, createApiClient } from '@fulfilment/common-services/client';

// Option 2: Import from main package with namespace
import { client } from '@fulfilment/common-services';
const apiClient = new client.ApiClient({ baseUrl: 'http://localhost:3000' });

// Option 3: Import from server module explicitly  
import { authMiddleware } from '@fulfilment/common-services/server';

API Client

import { createApiClient, createAuthClient } from '@fulfilment/common-services/client';

// Create API client
const apiClient = createApiClient({
  baseUrl: 'http://localhost:3000',
  timeout: 10000,
  onError: (error) => {
    console.error('API Error:', error.message);
  }
});

// Basic usage
const response = await apiClient.get('/api/users');
const users = response.data;

// With authentication token
apiClient.setAuthToken('your-jwt-token');
const protectedData = await apiClient.get('/api/protected');

// POST request
const newUser = await apiClient.post('/api/users', {
  name: 'John Doe',
  email: '[email protected]'
});

// Paginated requests
const paginatedUsers = await apiClient.getPaginated('/api/users', {
  page: 1,
  limit: 20,
  sort: 'created_at',
  order: 'desc'
});

Authentication Client

import { createAuthClient } from '@fulfilment/common-services/client';

const authClient = createAuthClient({
  storage: 'localStorage', // or 'sessionStorage' or 'memory'
  tokenKey: 'auth_token',
  onTokenExpired: () => {
    // Redirect to login or refresh token
    window.location.href = '/login';
  }
});

// Login and store tokens
const loginResponse = await apiClient.post('/auth/login', {
  email: '[email protected]',
  password: 'password'
});

authClient.setTokens({
  accessToken: loginResponse.data.token,
  refreshToken: loginResponse.data.refreshToken,
  expiresAt: Date.now() + 3600000 // 1 hour
});

// Check authentication status
if (authClient.isAuthenticated()) {
  const userProfile = authClient.getUserProfile();
  console.log('User:', userProfile);
}

// Get current token for API requests
const token = authClient.getAccessToken();
apiClient.setAuthToken(token);

Client Utilities

import { 
  buildApiUrl, 
  withRetry, 
  createPaginationInfo, 
  storage,
  cookies 
} from '@fulfilment/common-services/client';

// URL building
const url = buildApiUrl('http://localhost:3000', '/api/users', { 
  page: 1, 
  limit: 20 
});
// Result: "http://localhost:3000/api/users?page=1&limit=20"

// Retry logic
const dataWithRetry = await withRetry(
  () => apiClient.get('/api/unreliable-endpoint'),
  {
    maxRetries: 3,
    delay: 1000,
    backoff: 'exponential',
    retryCondition: (error) => error.status >= 500
  }
);

// Pagination helpers
const paginationInfo = createPaginationInfo(paginatedResponse);
console.log(`Showing ${paginationInfo.startIndex}-${paginationInfo.endIndex} of ${paginationInfo.totalItems}`);

// Local storage
storage.set('user-preferences', { theme: 'dark', language: 'en' });
const preferences = storage.get('user-preferences');

// Cookies
cookies.set('session-id', 'abc123', { 
  expires: new Date(Date.now() + 86400000), // 1 day
  secure: true,
  sameSite: 'strict'
});

React Hook Examples

// Custom hook for API calls
import { useEffect, useState } from 'react';
import { createApiClient } from '@fulfilment/common-services/client';

const apiClient = createApiClient({ baseUrl: process.env.REACT_APP_API_URL });

export function useApi<T>(endpoint: string) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    apiClient.get<T>(endpoint)
      .then(response => setData(response.data))
      .catch(err => setError(err.message))
      .finally(() => setLoading(false));
  }, [endpoint]);

  return { data, loading, error };
}

// Usage in component
function UserList() {
  const { data: users, loading, error } = useApi<User[]>('/api/users');
  
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  
  return (
    <ul>
      {users?.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

Migration Examples

Server-Side (Express API)

Before:

// Old tracking-api/src/index.ts
import express from 'express';
import cors from 'cors';
import { authMiddleware } from './middleware/auth';
// ... lots of boilerplate

After:

// New tracking-api/src/index.ts  
import { createFullApp } from '@fulfilment/common-services/server';
// or: import { createFullApp } from '@fulfilment/common-services';

const app = createFullApp({
  cors: { origins: ['http://localhost:3000'] },
  auth: { jwtSecret: process.env.JWT_SECRET },
  health: { serviceName: 'tracking-api' }
});

Client-Side (React/Vue/etc)

Before:

// Old frontend code
const response = await fetch('/api/users', {
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  }
});
const data = await response.json();

After:

// New frontend code
import { createApiClient } from '@fulfilment/common-services/client';

const apiClient = createApiClient({ baseUrl: '/api' });
apiClient.setAuthToken(token);
const { data } = await apiClient.get('/users');

Development

# Install dependencies
bun install

# Build the library  
bun run build

# Type check
bun run typecheck

# Watch mode for development
bun run dev