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

ar-common-lib

v1.0.5

Published

A utility library for the project providing geolocation services based on IP addresses and rate limiting functionality.

Readme

Utils

A utility library for the project providing geolocation services based on IP addresses and rate limiting functionality.

Features

  • IP geolocation lookup using multiple fallback APIs
  • Normalized response format across different data providers
  • Fault-tolerant design with automatic failover between services
  • Rate limiting for API endpoints with configurable limits

Installation

npm install ar-common-lib

Usage

Geolocation

import { getIpInfo } from 'ar-common-lib';

async function example() {
  const ipInfo = await getIpInfo('8.8.8.8');
  console.log(ipInfo);
  // Output: { ip: '8.8.8.8', country: 'United States', city: 'Mountain View', state: 'California', lat: '37.4056', lon: '-122.0775' }
}

Rate Limiting

// pages/api/protected-data.js
import { initRateLimit, getClientIp } from 'ar-common-lib';

// Configure this rate limiter:
// - Max 10 requests per minute per IP.
// - Track up to 1000 unique IPs in this window.
const limiter = initRateLimit({
  interval: 60 * 1000, // 1 minute in milliseconds
  uniqueTokenPerInterval: 1000, // Max 1000 unique IPs (maps to maxKeys)
  // stdTTL will be automatically set to 60 seconds
  // checkperiod will be automatically set based on stdTTL
});

export default async function handler(req, res) {
  const clientIp = getClientIp(req);

  if (!clientIp || clientIp === 'unknown') {
    console.warn('Could not determine client IP for rate limiting.');
    // Potentially handle anonymous users differently if needed
  }

  try {
    // Check the rate limit: 10 requests per minute for this IP
    const rateLimitResult = await limiter.check(10, clientIp || 'ANONYMOUS_USER');
    
    // Set rate limit headers (optional)
    res.setHeader('X-RateLimit-Limit', rateLimitResult.limit);
    res.setHeader('X-RateLimit-Remaining', rateLimitResult.remaining);
    res.setHeader('X-RateLimit-Reset', rateLimitResult.resetTime);

    res.status(200).json({
      message: 'This is protected data.',
      ip: clientIp,
      timestamp: new Date().toISOString(),
    });
  } catch (error) {
    // Rate limit exceeded, handle the error
    res.setHeader('Retry-After', error.resetTime);
    res.status(429).json({
      error: error.error,
      retryAfter: error.resetTime
    });
    return;
  }
}

Using isRateLimited Method

// Example of using isRateLimited for custom handling
import { initRateLimit, getClientIp } from 'ar-common-lib';

const limiter = initRateLimit({
  interval: 60 * 1000,
  uniqueTokenPerInterval: 1000,
});

export default function handler(req, res) {
  const clientIp = getClientIp(req);
  const token = clientIp || 'ANONYMOUS_USER';
  
  // Check if the request is rate limited (this will increment the counter)
  const isLimited = limiter.isRateLimited(5, token);
  
  if (isLimited) {
    // Custom handling for rate limited requests
    return res.status(429).json({
      error: 'Custom rate limit error message',
      retryAfter: 60, // seconds
    });
  }
  
  // Process the request normally
  return res.status(200).json({
    message: 'Request processed successfully',
  });
}

API Reference

Geolocation

getIpInfo(ip)

Retrieves geolocation information for a given IP address.

Parameters:

  • ip (string): The IP address to look up

Returns: A Promise that resolves to an object with the following properties:

  • ip: The input IP address
  • country: Country name
  • city: City name
  • state: State or region name
  • lat: Latitude coordinate
  • lon: Longitude coordinate

Rate Limiting

initRateLimit(options)

Initializes a rate limiter with the specified options.

Parameters:

  • options (object): Configuration options
    • interval (number): Time window in milliseconds (default: 60000)
    • uniqueTokenPerInterval (number): Maximum number of unique tokens to track (default: 500)
    • stdTTL (number): Default TTL for items in seconds (automatically set based on interval if not provided)
    • checkperiod (number): How often to check for expired items in seconds (automatically set based on stdTTL if not provided)
    • customKey (string): Optional identifier for this rate limiter instance

Returns: An object with the following methods:

  • check(limit, token): Checks if the request is within rate limits and returns rate limit information
  • isRateLimited(limit, token): Checks if a token exceeds the rate limit and increments its counter

The check method returns a Promise that resolves with the following information:

{
  success: true,
  currentUsage: number, // Current count for the token
  limit: number, // Maximum allowed requests
  remaining: number, // Requests remaining in the window
  resetTime: number // Seconds until the rate limit resets
}

If the rate limit is exceeded, the Promise rejects with an error object:

{
  error: string, // User-friendly error message
  resetTime: number, // Seconds until the rate limit resets
  limit: number, // Maximum allowed requests
  token: string, // The token that exceeded the limit
  message: string // Detailed error message
}

getClientIp(req)

Helper function to extract the client IP address from a request object.

Parameters:

  • req (object): HTTP request object

Returns: A string containing the client's IP address

Data Sources

The library attempts to retrieve data from the free services in sequence until a successful response is received:

Testing

To run the test script:

node src/test-geo.js

Dependencies

  • axios: HTTP client for making API requests

License

ISC