New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

queue-it-sdk

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

queue-it-sdk

Shared types, utilities, and realtime adapters for Queue-it system

latest
npmnpm
Version
1.0.4
Version published
Maintainers
1
Created
Source

Queue-it SDK

A comprehensive TypeScript SDK for building virtual waiting room systems with real-time capabilities.

🚀 Quick Start

Installation

# In your project
pnpm add @queue-it/queue-sdk

# Or if using the monorepo
pnpm add @queue-it/queue-sdk --workspace

Basic Usage

import { 
  createRealtimeClient, 
  TokenUtils, 
  CookieUtils,
  withWaitingRoom,
  type QueueConfig,
  type QueueState 
} from '@queue-it/queue-sdk';

// Initialize realtime client
const realtimeClient = createRealtimeClient({
  driver: 'socketio',
  url: 'https://your-api.com',
  auth: {
    token: 'your-auth-token'
  }
});

// Connect to realtime service
await realtimeClient.connect();

// Subscribe to queue updates
const unsubscribe = realtimeClient.subscribeQueue('limited-sneakers', (message) => {
  console.log('Queue update:', message);
  
  if (message.type === 'position_update') {
    console.log(`Your position: ${message.data.position}`);
    console.log(`Estimated wait time: ${message.data.estimatedWaitTime} seconds`);
  }
  
  if (message.type === 'admitted') {
    console.log('You have been admitted!');
    unsubscribe();
  }
});

🔧 Environment Setup

Environment Variables

The Queue SDK uses environment variables for development and testing. Copy the env.example file to .env and modify as needed:

# Copy the example file
cp env.example .env

Required Environment Variables

# API Configuration
QUEUE_API_URL=http://localhost:4000
QUEUE_WS_URL=ws://localhost:4000

# Authentication
QUEUE_AUTH_ENABLED=true
QUEUE_AUTH_COOKIE_NAME=queue-auth

Optional Environment Variables

# Queue Configuration
QUEUE_DEFAULT_TIMEOUT=30000
QUEUE_MAX_RETRIES=3

# Development
QUEUE_DEBUG_ENABLED=true
QUEUE_LOG_LEVEL=info

Environment Setup Checklist

  • Copy env.example: cp env.example .env
  • Set API URL: Point to your Queue API server
  • Configure WebSocket: Set WebSocket URL for real-time updates
  • Enable authentication: Configure auth settings for your use case
  • Set timeouts: Configure queue timeout and retry settings
  • Enable debugging: Set debug flags for development

Production Environment Variables

For production deployment:

  • API URLs: Use production Queue API endpoints
  • WebSocket URLs: Use production WebSocket endpoints
  • Authentication: Ensure proper auth configuration
  • Timeouts: Set appropriate timeout values for production
  • Debugging: Disable debug features in production

📚 API Reference

Realtime Client

createRealtimeClient(config: RealtimeConfig): RealtimeClient

Creates a realtime client for queue updates.

interface RealtimeConfig {
  driver: 'socketio' | 'sse';           // Transport protocol
  url: string;                          // Server URL
  auth?: {                              // Authentication
    token?: string;
    headers?: Record<string, string>;
  };
  options?: {                           // Connection options
    reconnection?: boolean;
    reconnectionDelay?: number;
    maxReconnectionAttempts?: number;
    timeout?: number;
  };
}

RealtimeClient.connect(): Promise<void>

Establishes connection to the realtime service.

try {
  await realtimeClient.connect();
  console.log('Connected to realtime service');
} catch (error) {
  console.error('Connection failed:', error);
}

RealtimeClient.subscribeQueue(queueId: string, handler: QueueMessageHandler): () => void

Subscribes to queue updates. Returns an unsubscribe function.

const unsubscribe = realtimeClient.subscribeQueue('queue-id', (message) => {
  switch (message.type) {
    case 'queue_update':
      console.log('Queue state updated:', message.data);
      break;
    case 'position_update':
      console.log('Position:', message.data.position);
      break;
    case 'admitted':
      console.log('Admitted to queue!');
      break;
    case 'error':
      console.error('Error:', message.data.message);
      break;
  }
});

// Later, unsubscribe
unsubscribe();

RealtimeClient.disconnect(): void

Disconnects from the realtime service.

realtimeClient.disconnect();

RealtimeClient.isConnected(): boolean

Checks if the client is connected.

if (realtimeClient.isConnected()) {
  console.log('Client is connected');
}

Token Utilities

TokenUtils

Handles JWT and HMAC token operations.

import { TokenUtils } from '@queue-it/queue-sdk';

const tokenUtils = new TokenUtils(
  'your-hmac-secret',
  'your-jwt-secret'
);

// Generate HMAC signature for enqueue ticket
const ticket = {
  nonce: 'abc123',
  visitorId: 'visitor-456',
  queueId: 'limited-sneakers',
  issuedAt: new Date(),
  expiresAt: new Date(Date.now() + 3600000)
};

const signature = tokenUtils.generateTicketSignature(ticket);

// Verify ticket signature
const isValid = tokenUtils.verifyTicketSignature({
  ...ticket,
  signature
});

// Generate JWT for queue access
const queueToken = tokenUtils.generateQueueToken(visitor, '1h');

// Verify JWT token
const decoded = tokenUtils.verifyQueueToken(queueToken);

// Generate admin token
const adminToken = tokenUtils.generateAdminToken('user-123', 'admin', '24h');

// Verify admin token
const adminData = tokenUtils.verifyAdminToken(adminToken);

Static Methods

// Generate secure nonce
const nonce = TokenUtils.generateNonce();

// Generate visitor ID
const visitorId = TokenUtils.generateVisitorId();

// Check if token is expired
const isExpired = TokenUtils.isExpired(expiresAt);

// Calculate time until expiration
const timeLeft = TokenUtils.timeUntilExpiration(expiresAt);

CookieUtils

Manages secure HTTP-only cookies.

import { CookieUtils } from '@queue-it/queue-sdk';

const cookieUtils = new CookieUtils('yourdomain.com', true);

// Set queue token cookie
cookieUtils.setQueueTokenCookie(res, token);

// Set admin token cookie
cookieUtils.setAdminTokenCookie(res, adminToken);

// Get cookies from request
const queueToken = cookieUtils.getQueueToken(req);
const adminToken = cookieUtils.getAdminToken(req);

// Clear cookies
cookieUtils.clearQueueToken(res);
cookieUtils.clearAdminToken(res);

Next.js Middleware

withWaitingRoom(config: WaitingRoomConfig)

Protects routes with waiting room functionality.

// middleware.ts
import { withWaitingRoom } from '@queue-it/queue-sdk';

export default withWaitingRoom({
  queueId: 'limited-sneakers',
  jwtSecret: process.env.JWT_SECRET!,
  hmacSecret: process.env.HMAC_SECRET!,
  cookieDomain: process.env.COOKIE_DOMAIN!,
  bypassToken: process.env.BYPASS_TOKEN // Optional, for testing
});

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * - waiting-room (waiting room pages)
     */
    '/((?!api|_next/static|_next/image|favicon.ico|waiting-room).*)',
  ],
};

Alternative Middleware Function

import { createWaitingRoomMiddleware } from '@queue-it/queue-sdk';

export default createWaitingRoomMiddleware({
  queueId: 'limited-sneakers',
  jwtSecret: process.env.JWT_SECRET!,
  hmacSecret: process.env.HMAC_SECRET!,
  cookieDomain: process.env.COOKIE_DOMAIN!
});

Admin Client

⚠️ IMPORTANT: The AdminClient is designed for server-side use only. It should not be used in browser/client-side code as it contains Node.js-specific dependencies that won't work in browsers. Use it in API routes, server components, or backend services only.

createAdminClient(config: AdminClientConfig): AdminClient

Creates an admin client for managing queues programmatically.

import { createAdminClient } from '@queue-it/queue-sdk';

const adminClient = createAdminClient({
  baseUrl: 'https://admin-api.example.com',
  apiKey: 'your-admin-api-key' // Optional
});

Queue Management Methods

// Create a queue
const queue = await adminClient.createQueue({
  name: 'Limited Sneakers',
  description: 'Queue for limited sneaker drop',
  mode: 'fifo',
  capacity: 1000,
  triggerThreshold: 100,
  rampRate: 10
});

// List all queues
const queues = await adminClient.listQueues();

// Get specific queue
const queue = await adminClient.getQueue('queue-id');

// Update queue
const updatedQueue = await adminClient.updateQueue('queue-id', {
  capacity: 1500,
  isActive: true
});

// Delete queue
await adminClient.deleteQueue('queue-id');

Client-Side Queue Creation

// Create queue based on client endpoint/event
const queue = await adminClient.createQueueFromEndpoint('/api/events/limited-drop', {
  mode: 'timed_random',
  capacity: 500,
  triggerThreshold: 50,
  rampRate: 5
});

// This creates a queue with name like "queue-limited-drop"
// and metadata indicating it was created from an endpoint

Route-Based User Enqueuing

// Enqueue user when they hit a specific route
const result = await adminClient.enqueueUserOnRoute('/checkout', 'visitor-123', {
  userAgent: 'Mozilla/5.0...',
  ipAddress: '192.168.1.1'
});

// This automatically finds or creates a queue for the /checkout route
// and enqueues the user with route metadata

Admin UI Socket Connection

// Establish socket connection for admin dashboard
const realtimeClient = adminClient.createAdminRealtimeConnection({
  authToken: 'admin-jwt-token',
  reconnection: true,
  maxReconnectionAttempts: 5
});

// Connect and subscribe to queue updates
await realtimeClient.connect();

const unsubscribe = realtimeClient.subscribeQueue('all', (message) => {
  console.log('Admin queue update:', message);
});

Visitor Management

// Enqueue a visitor manually
const enqueueResult = await adminClient.enqueueVisitor({
  queueId: 'limited-sneakers',
  visitorId: 'visitor-123',
  metadata: {
    source: 'website',
    priority: 'vip'
  }
});

console.log('Enqueued at position:', enqueueResult.position);
console.log('Estimated wait time:', enqueueResult.estimatedWaitTime);

🔧 Usage Examples

1. Client-Side Queue Integration

// components/QueueWidget.tsx
import { createRealtimeClient, type QueueMessage } from '@queue-it/queue-sdk';
import { useEffect, useState } from 'react';

interface QueueWidgetProps {
  queueId: string;
  authToken: string;
}

export function QueueWidget({ queueId, authToken }: QueueWidgetProps) {
  const [position, setPosition] = useState<number | null>(null);
  const [estimatedWaitTime, setEstimatedWaitTime] = useState<number | null>(null);
  const [isAdmitted, setIsAdmitted] = useState(false);

  useEffect(() => {
    const realtimeClient = createRealtimeClient({
      driver: 'socketio',
      url: process.env.NEXT_PUBLIC_WS_URL!,
      auth: { token: authToken }
    });

    const connect = async () => {
      try {
        await realtimeClient.connect();
        
        const unsubscribe = realtimeClient.subscribeQueue(queueId, (message: QueueMessage) => {
          if (message.type === 'position_update') {
            setPosition(message.data.position);
            setEstimatedWaitTime(message.data.estimatedWaitTime);
          } else if (message.type === 'admitted') {
            setIsAdmitted(true);
            unsubscribe();
          }
        });
        
        return unsubscribe;
      } catch (error) {
        console.error('Failed to connect:', error);
      }
    };

    const unsubscribe = connect();
    
    return () => {
      unsubscribe?.();
      realtimeClient.disconnect();
    };
  }, [queueId, authToken]);

  if (isAdmitted) {
    return <div>Welcome! You have been admitted.</div>;
  }

  return (
    <div className="queue-widget">
      <h3>Queue Position</h3>
      {position !== null ? (
        <>
          <p>Your position: <strong>{position}</strong></p>
          {estimatedWaitTime !== null && (
            <p>Estimated wait: <strong>{estimatedWaitTime} seconds</strong></p>
          )}
        </>
      ) : (
        <p>Loading queue information...</p>
      )}
    </div>
  );
}

2. Server-Side Token Validation

// lib/auth.ts
import { TokenUtils } from '@queue-it/queue-sdk';

const tokenUtils = new TokenUtils(
  process.env.HMAC_SECRET!,
  process.env.JWT_SECRET!
);

export function validateQueueToken(token: string) {
  try {
    const decoded = tokenUtils.verifyQueueToken(token);
    if (!decoded) {
      return null;
    }
    
    if (TokenUtils.isExpired(decoded.expiresAt)) {
      return null;
    }
    
    return decoded;
  } catch (error) {
    return null;
  }
}

export function validateAdminToken(token: string) {
  try {
    return tokenUtils.verifyAdminToken(token);
  } catch (error) {
    return null;
  }
}

3. API Route with Queue Management

// pages/api/queue/enqueue.ts
import { TokenUtils } from '@queue-it/queue-sdk';
import type { NextApiRequest, NextApiResponse } from 'next';

const tokenUtils = new TokenUtils(
  process.env.HMAC_SECRET!,
  process.env.JWT_SECRET!
);

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const { queueId, visitorId } = req.body;

    // Generate enqueue ticket
    const nonce = TokenUtils.generateNonce();
    const issuedAt = new Date();
    const expiresAt = new Date(issuedAt.getTime() + 3600000); // 1 hour

    const ticket = {
      nonce,
      visitorId: visitorId || TokenUtils.generateVisitorId(),
      queueId,
      issuedAt,
      expiresAt
    };

    const signature = tokenUtils.generateTicketSignature(ticket);

    // Here you would typically:
    // 1. Add visitor to queue in Redis
    // 2. Store ticket information
    // 3. Emit realtime updates

    res.status(200).json({
      success: true,
      ticket: { ...ticket, signature },
      position: 1, // This would come from your queue logic
      estimatedWaitTime: 300 // This would be calculated
    });
  } catch (error) {
    console.error('Enqueue error:', error);
    res.status(500).json({ error: 'Failed to enqueue visitor' });
  }
}

4. Express.js Integration

// app.ts
import express from 'express';
import { CookieUtils, TokenUtils } from '@queue-it/queue-sdk';

const app = express();
const cookieUtils = new CookieUtils('yourdomain.com', true);
const tokenUtils = new TokenUtils(
  process.env.HMAC_SECRET!,
  process.env.JWT_SECRET!
);

// Middleware to validate queue tokens
app.use('/protected', (req, res, next) => {
  const token = cookieUtils.getQueueToken(req);
  
  if (!token) {
    return res.status(401).json({ error: 'No token provided' });
  }
  
  const decoded = tokenUtils.verifyQueueToken(token);
  if (!decoded) {
    return res.status(401).json({ error: 'Invalid token' });
  }
  
  if (TokenUtils.isExpired(decoded.expiresAt)) {
    cookieUtils.clearQueueToken(res);
    return res.status(401).json({ error: 'Token expired' });
  }
  
  // Add user info to request
  req.user = decoded;
  next();
});

app.get('/protected/dashboard', (req, res) => {
  res.json({ 
    message: 'Welcome to dashboard',
    visitorId: req.user.visitorId,
    position: req.user.position
  });
});

5. React Hook for Queue Management

// hooks/useQueue.ts
import { createRealtimeClient, type QueueMessage } from '@queue-it/queue-sdk';
import { useEffect, useState, useCallback } from 'react';

interface UseQueueOptions {
  queueId: string;
  authToken: string;
  autoConnect?: boolean;
}

export function useQueue({ queueId, authToken, autoConnect = true }: UseQueueOptions) {
  const [isConnected, setIsConnected] = useState(false);
  const [queueState, setQueueState] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);
  const [realtimeClient, setRealtimeClient] = useState<any>(null);

  const connect = useCallback(async () => {
    try {
      const client = createRealtimeClient({
        driver: 'socketio',
        url: process.env.NEXT_PUBLIC_WS_URL!,
        auth: { token: authToken }
      });

      await client.connect();
      setIsConnected(true);
      setRealtimeClient(client);
      setError(null);

      // Subscribe to queue updates
      client.subscribeQueue(queueId, (message: QueueMessage) => {
        if (message.type === 'queue_update') {
          setQueueState(message.data);
        }
      });

      return client;
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Connection failed');
      setIsConnected(false);
      throw err;
    }
  }, [queueId, authToken]);

  const disconnect = useCallback(() => {
    if (realtimeClient) {
      realtimeClient.disconnect();
      setIsConnected(false);
      setRealtimeClient(null);
    }
  }, [realtimeClient]);

  useEffect(() => {
    if (autoConnect) {
      connect();
    }

    return () => {
      disconnect();
    };
  }, [autoConnect, connect, disconnect]);

  return {
    isConnected,
    queueState,
    error,
    connect,
    disconnect
  };
}

🖥️ Server vs Client Usage

Server-Side Components (API Routes, Server Components)

Use these in Node.js environments (API routes, server components, backend services):

  • AdminClient: For managing queues, creating endpoints, enqueuing users
  • TokenUtils: For JWT token generation and validation
  • CookieUtils: For secure cookie management
  • withWaitingRoom: Next.js middleware for route protection

Client-Side Components (React Components, Browser)

Use these in browser environments:

  • RealtimeClient: For real-time queue updates and position tracking
  • QueueWidget: Pre-built React components for queue UI
  • createRealtimeClient: For establishing WebSocket connections

Example Architecture

// Server-side: API route (pages/api/admin/queues.ts)
import { createAdminClient } from '@queue-it/queue-sdk';

export default async function handler(req, res) {
  const adminClient = createAdminClient({
    baseUrl: process.env.ADMIN_API_URL,
    apiKey: process.env.ADMIN_API_KEY
  });

  if (req.method === 'POST') {
    const queue = await adminClient.createQueueFromEndpoint('/api/events/sale');
    res.status(200).json(queue);
  }
}

// Client-side: React component
import { createRealtimeClient } from '@queue-it/queue-sdk';

function QueueComponent() {
  const realtimeClient = createRealtimeClient({
    driver: 'socketio',
    url: process.env.NEXT_PUBLIC_WS_URL
  });

  // Use realtimeClient in component
}

🔒 Security Considerations

Token Security

  • JWT Secrets: Use strong, randomly generated secrets
  • HMAC Secrets: Keep HMAC secrets separate from JWT secrets
  • Token Expiration: Set appropriate expiration times
  • Secure Cookies: Always use httpOnly and secure flags in production

Rate Limiting

// Example rate limiting with the SDK
import rateLimit from 'express-rate-limit';

const enqueueLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // limit each IP to 5 enqueue requests per windowMs
  message: 'Too many enqueue attempts, please try again later'
});

app.post('/api/queue/enqueue', enqueueLimiter, enqueueHandler);

🧪 Testing

Unit Tests

// __tests__/TokenUtils.test.ts
import { TokenUtils } from '@queue-it/queue-sdk';

describe('TokenUtils', () => {
  const tokenUtils = new TokenUtils('test-hmac-secret', 'test-jwt-secret');

  test('should generate and verify HMAC signature', () => {
    const ticket = {
      nonce: 'test-nonce',
      visitorId: 'test-visitor',
      queueId: 'test-queue',
      issuedAt: new Date(),
      expiresAt: new Date(Date.now() + 3600000)
    };

    const signature = tokenUtils.generateTicketSignature(ticket);
    const isValid = tokenUtils.verifyTicketSignature({ ...ticket, signature });

    expect(isValid).toBe(true);
  });

  test('should generate and verify JWT token', () => {
    const visitor = {
      id: 'test-visitor',
      queueId: 'test-queue',
      position: 1,
      joinedAt: new Date(),
      lastHeartbeat: new Date(),
      isActive: false,
      metadata: {}
    };

    const token = tokenUtils.generateQueueToken(visitor);
    const decoded = tokenUtils.verifyQueueToken(token);

    expect(decoded).toBeTruthy();
    expect(decoded?.visitorId).toBe('test-visitor');
  });
});

Integration Tests

// __tests__/integration/RealtimeClient.test.ts
import { createRealtimeClient } from '@queue-it/queue-sdk';

describe('RealtimeClient Integration', () => {
  test('should connect and receive messages', async () => {
    const client = createRealtimeClient({
      driver: 'socketio',
      url: 'http://localhost:4000'
    });

    const messages: any[] = [];
    
    await client.connect();
    
    const unsubscribe = client.subscribeQueue('test-queue', (message) => {
      messages.push(message);
    });

    // Wait for messages
    await new Promise(resolve => setTimeout(resolve, 1000));

    expect(client.isConnected()).toBe(true);
    expect(messages.length).toBeGreaterThan(0);

    unsubscribe();
    client.disconnect();
  });
});

📱 Browser Support

  • Socket.IO: Modern browsers with WebSocket support
  • SSE: All modern browsers (IE 10+)
  • Fallback: Automatic fallback to polling if needed

🔧 Configuration

Environment Variables

The Queue SDK requires these environment variables for production use:

# Required
JWT_SECRET=your-super-secure-jwt-secret
HMAC_SECRET=your-super-secure-hmac-secret

# Optional
COOKIE_DOMAIN=yourdomain.com
COOKIE_SECURE=true

Note: For development setup, see the Environment Setup section above.

TypeScript Configuration

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}

🆘 Troubleshooting

Common Issues

  • Connection Failed

    • Check server URL and port
    • Verify authentication token
    • Check CORS configuration
  • Token Validation Errors

    • Verify JWT and HMAC secrets
    • Check token expiration
    • Ensure proper token format
  • Cookie Issues

    • Verify domain configuration
    • Check secure flag in production
    • Ensure proper SameSite policy

Debug Mode

// Enable debug logging
const realtimeClient = createRealtimeClient({
  driver: 'socketio',
  url: 'https://your-api.com',
  options: {
    reconnection: true,
    reconnectionDelay: 1000,
    maxReconnectionAttempts: 5
  }
});

// Listen for connection events
realtimeClient.on('connect', () => console.log('Connected'));
realtimeClient.on('disconnect', () => console.log('Disconnected'));
realtimeClient.on('error', (error) => console.error('Error:', error));

📚 Additional Resources

🤝 Contributing

  • Fork the repository
  • Create a feature branch
  • Make your changes
  • Add tests
  • Submit a pull request

📄 License

MIT License - see LICENSE file for details

Keywords

queue

FAQs

Package last updated on 06 Oct 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts