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

@k15/location-service

v1.0.3

Published

Library berisi service (function) untuk menentukan lokasi terkini, jarak dengan titik lokasi tertentu, menggunakan library third party lain

Readme

Location-Service 📍

A lightweight, framework-agnostic geohash-based caching system for location data with built-in Nominatim API integration. Perfect for reducing API calls while providing accurate city name lookups based on coordinates.

🌟 Credits

This package uses the Nominatim API from OpenStreetMap for reverse geocoding functionality:

Powered by nominatim.openstreemap

  • Nominatim: Open-source geocoding using OpenStreetMap data
  • OpenStreetMap: The free, editable map of the world, created and maintained by volunteers

Please respect OpenStreetMap's usage policy and consider contributing to their amazing project!

Features

🗺️ Automatic Nominatim Integration - Built-in OpenStreetMap reverse geocoding

💾 Multiple Storage Options - Memory, localStorage, and sessionStorage support

⚡ Smart Caching - Finds nearby cached results to minimize API calls

🎯 Accurate Distance Calculations - Haversine formula implementation

🔄 Automatic Cleanup - Removes expired entries automatically

📱 Framework Agnostic - Works with React, Vue, Angular, and vanilla JS

🛡️ Rate Limiting - Respects Nominatim's usage policies

Installation

npm install @k15/location-service

or using yarn:

yarn add @k15/location-service

Quick Start

Basic Usage

import { GeohashCache } from '@k15/location-service';

// Create cache instance
const cache = new GeohashCache();

// Get city name - automatically handles caching and API calls
async function getCityName(lat, lon) {
  try {
    const result = await cache.getCityName(lat, lon);
    console.log(`City: ${result.name}`);
    console.log(`Full address: ${result.fullAddress}`);
    return result.name;
  } catch (error) {
    console.error('Error:', error);
    return 'Unknown location';
  }
}

// Usage
getCityName(40.7128, -74.0060); // New York
getCityName(51.5074, -0.1278);  // London

React Example

import { useState, useEffect } from 'react';
import { GeohashCache } from '@k15/location-service';

function CityDisplay() {
  const [city, setCity] = useState('');
  const [cache] = useState(() => new GeohashCache({
    storageType: 'localStorage', // Persist between sessions
    defaultExpiry: 24 * 60 * 60 * 1000 // 24 hours
  }));

  useEffect(() => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        async (position) => {
          const { latitude, longitude } = position.coords;
          const result = await cache.getCityName(latitude, longitude);
          setCity(result.name);
        },
        (error) => console.error('Geolocation error:', error)
      );
    }
  }, []);

  return <div>Your city: {city || 'Loading...'}</div>;
}

Vue 3 Example

<template>
  <div>
    <p>Your city: {{ cityName }}</p>
    <button @click="getLocation">Find My City</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { GeohashCache } from '@k15/location-service';

const cityName = ref('');
const cache = ref(new GeohashCache());

const getLocation = () => {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(
      async (position) => {
        const { latitude, longitude } = position.coords;
        const result = await cache.value.getCityName(latitude, longitude);
        cityName.value = result.name;
      },
      (error) => console.error('Error getting location:', error)
    );
  }
};
</script>

API Reference

GeohashCache Constructor Options

const cache = new GeohashCache({
  defaultExpiry: 30 * 60 * 1000,    // Cache expiry time (30 minutes)
  precision: 4,                      // Coordinate rounding precision (decimal places)
  maxSize: 1000,                     // Maximum cache entries
  cleanupInterval: 5 * 60 * 1000,    // Cleanup trigger interval (used during cleanup operations)
  nominatimEndpoint: 'https://nominatim.openstreetmap.org/reverse',
  requestDelay: 1000,                // Delay between API calls (1 second)
  userAgent: 'location-service/1.0.0',  // User agent for API requests
  storageType: 'memory',             // 'memory' | 'localStorage' | 'sessionStorage'
  storageKey: 'geohash_cache'        // Key for storage
});

Methods

  • getCityName(lat: number, lon: number): Promise<CityResult>

    • Get city name for coordinates. Uses cache first (including nearby cached results), then API if needed.
  • set(lat: number, lon: number, value: any, customExpiry?: number): void

    • Manually add an entry to the cache.
  • get(lat: number, lon: number): any | null

    • Get cached value for exact rounded coordinates or null.
  • getWithinRadius(lat: number, lon: number, maxDistance?: number): any | null

    • Find closest cached result within radius (meters).
  • clear(): Promise<void>

    • Clear all cached data from memory and persistent storage.
const result = await cache.getCityName(40.7128, -74.0060);
// {
//   name: "New York",
//   fullAddress: "New York, NY, USA",
//   details: { city: "New York", state: "NY", country: "USA" },
//   coordinate: { lat: 40.7128, lon: -74.0060 }
// }

Storage Options

Memory Storage (Default)

// Only lasts during current runtime
const cache = new GeohashCache({ storageType: 'memory' });

LocalStorage

// Persists between browser sessions
const cache = new GeohashCache({ 
  storageType: 'localStorage',
  storageKey: 'my_app_geo_cache' // Custom storage key
});

SessionStorage

// Persists only during current tab session
const cache = new GeohashCache({ storageType: 'sessionStorage' });

Error Handling

import { GeohashCache } from '@k15/location-service';

const cache = new GeohashCache();

async function getCitySafe(lat, lon) {
  try {
    return await cache.getCityName(lat, lon);
  } catch (error) {
    console.warn('API failed, trying fallback:', error);
    // Try to get nearby cached result as a fallback
    const fallback = cache.getWithinRadius(lat, lon, 10000);
    if (fallback) return fallback;
    return {
      name: 'Unknown Location',
      fullAddress: '',
      details: {},
      coordinate: { lat, lon }
    };
  }
}

Best Practices

  1. Proper User Agent
// Always set a proper user agent
const cache = new GeohashCache({
  userAgent: 'your-app-name/version ([email protected])'
});
  1. Respect Rate Limits
// Use appropriate delays between requests
const cache = new GeohashCache({
  requestDelay: 2000 // 2 seconds between API calls
});
  1. Cache Expiry Strategy
// Balance between freshness and API calls
const cache = new GeohashCache({
  defaultExpiry: 24 * 60 * 60 * 1000, // 24 hours for city data
  precision: 4 // decimal rounding of coordinates
});
  1. Storage Management
// Use localStorage for persistence, but limit size
const cache = new GeohashCache({
  storageType: 'localStorage',
  maxSize: 200 // Prevent storage bloat
});

Browser Support

This package supports all modern browsers that support:

  • ES2015+
  • Promises
  • Fetch API
  • localStorage/sessionStorage

For older browsers, you may need polyfills for:

  • Promise
  • fetch
  • Object.entries
  • Map

License

ISC License

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

If you have any issues or questions, please file an issue on the GitHub repository.

Happy coding! 🚀