Skip to content

geonot/opencage-javascript

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OpenCage JavaScript SDK

NPM Version Bundle Size License Test Coverage

A zero-dependency, frontend-optimized JavaScript SDK for the OpenCage Geocoding API. Built for modern browsers with comprehensive TypeScript definitions and enterprise-grade features.

✨ Features

  • πŸš€ Zero Dependencies - Pure JavaScript with no external dependencies
  • 🎯 Frontend Optimized - Built specifically for browser environments
  • πŸ’Ύ Intelligent Caching - Memory-based LRU cache with TTL support
  • ⚑ Debounced Requests - Automatic rate limiting for user input scenarios
  • πŸ”„ Retry Logic - Automatic retry with exponential backoff
  • πŸ“Š Usage Statistics - Built-in request tracking and analytics
  • πŸ›‘οΈ Input Validation - Comprehensive parameter validation and sanitization
  • 🌐 Multiple Formats - ES6 modules, CommonJS, and UMD builds
  • πŸ“± Mobile Friendly - Optimized for mobile and low-bandwidth connections
  • πŸ”§ TypeScript Ready - Full TypeScript definitions included

πŸš€ Quick Start

Installation

npm install @digiphilo/opencage-javascript

Basic Usage

import OpenCageClient from '@digiphilo/opencage-javascript'

// Initialize client
const client = new OpenCageClient({
  apiKey: 'YOUR_API_KEY'
})

// Forward geocoding (address β†’ coordinates)
const forwardResult = await client.geocode('1600 Pennsylvania Avenue, Washington, DC')
console.log(forwardResult.results[0].geometry) // { lat: 38.8976633, lng: -77.0365739 }

// Reverse geocoding (coordinates β†’ address)
const reverseResult = await client.reverseGeocode(38.8976633, -77.0365739)
console.log(reverseResult.results[0].formatted) // "White House, ..."

// Get rate limit info
const rateInfo = client.getRateLimitInfo()
console.log(`${rateInfo.remaining}/${rateInfo.limit} requests remaining`)

Browser Usage (UMD)

<script src="https://unpkg.com/@digiphilo/opencage-javascript/dist/index.umd.min.js"></script>
<script>
  const client = new OpenCage.OpenCageClient({
    apiKey: 'YOUR_API_KEY'
  })
  
  client.geocode('London, UK').then(result => {
    console.log(result.results[0].formatted)
  })
</script>

πŸ“š Documentation

Configuration Options

const client = new OpenCageClient({
  apiKey: 'YOUR_API_KEY',        // Required: Your OpenCage API key
  timeout: 10000,                // Request timeout in milliseconds (default: 10000)
  retryAttempts: 3,              // Number of retry attempts (default: 3)
  retryDelay: 1000,              // Base retry delay in milliseconds (default: 1000)
  cache: true,                   // Enable caching (default: true)
  cacheSize: 100,                // Maximum cache entries (default: 100)
  cacheTtl: 300000,              // Cache TTL in milliseconds (default: 5 minutes)
  debounce: 300,                 // Debounce delay for rapid requests (default: 300ms)
  baseUrl: 'https://api.opencagedata.com/geocode/v1' // API base URL
})

Forward Geocoding

Convert addresses and place names to coordinates:

// Simple string query
const result = await client.geocode('Paris, France')

// Advanced query with options
const result = await client.geocode({
  query: '10 Downing Street',
  country: 'gb',           // Restrict to UK
  language: 'en',          // Results in English
  limit: 5,                // Maximum results
  bounds: [51.3, -0.2, 51.6, 0.1], // Bounding box [minlat, minlng, maxlat, maxlng]
  proximity: [51.5074, -0.1278],    // Bias results near this point
  minConfidence: 7,        // Minimum confidence score
  noAnnotations: true,     // Skip additional metadata
  abbrv: true             // Use abbreviated results
})

// Debounced geocoding (great for search-as-you-type)
const result = await client.debouncedGeocode('New Y') // Won't execute immediately
const result = await client.debouncedGeocode('New Yo') // Cancels previous
const result = await client.debouncedGeocode('New York') // Executes after delay

Reverse Geocoding

Convert coordinates to addresses:

// Basic reverse geocoding
const result = await client.reverseGeocode(40.7128, -74.0060)

// With options
const result = await client.reverseGeocode(40.7128, -74.0060, {
  language: 'es',          // Results in Spanish
  limit: 1,                // Only one result
  minConfidence: 5,        // Minimum confidence
  noAnnotations: true      // Skip metadata
})

// Debounced reverse geocoding
const result = await client.debouncedReverseGeocode(lat, lng, options)

Batch Geocoding

Process multiple queries efficiently:

const queries = [
  'London, UK',
  'Paris, France',
  { query: 'Tokyo, Japan', language: 'ja' }
]

const { results, errors } = await client.batchGeocode(queries, (progress) => {
  console.log(`Progress: ${progress.percentage}% (${progress.completed}/${progress.total})`)
  if (progress.errors.length > 0) {
    console.log('Errors:', progress.errors)
  }
})

// Process results
results.forEach((result, index) => {
  if (result) {
    console.log(`Query ${index}:`, result.results[0].formatted)
  } else {
    console.log(`Query ${index} failed`)
  }
})

Cache Management

Control caching behavior:

// Clear all cached results
client.clearCache()

// Get cache statistics
const stats = client.getCacheStats()
console.log(`Cache: ${stats.size}/${stats.maxSize} entries, ${stats.hitRate}% hit rate`)

// Disable cache temporarily
client.updateOptions({ cache: false })

// Re-enable with different settings
client.updateOptions({ 
  cache: true, 
  cacheSize: 200, 
  cacheTtl: 600000 // 10 minutes
})

Statistics and Monitoring

Track API usage and performance:

const stats = client.getStats()
console.log({
  totalRequests: stats.totalRequests,
  errors: stats.errors,
  cacheHits: stats.cacheHits,
  cacheMisses: stats.cacheMisses,
  lastRequest: stats.lastRequest,
  rateLimit: stats.rateLimit
})

// Reset statistics
client.resetStats()

// Check remaining API quota
const rateInfo = client.getRateLimitInfo()
if (rateInfo.remaining < 100) {
  console.warn('Low API quota remaining:', rateInfo.remaining)
}

Error Handling

Comprehensive error handling with context:

try {
  const result = await client.geocode('invalid query')
} catch (error) {
  console.error('Geocoding failed:', {
    message: error.message,
    code: error.code,
    status: error.status,
    operation: error.operation,  // 'forward' or 'reverse'
    context: error.context,      // Original query/parameters
    timestamp: error.timestamp,
    rateLimitRemaining: error.rateLimitRemaining
  })
  
  // Handle specific error types
  if (error.code === 402) {
    console.error('Quota exceeded - upgrade your plan')
  } else if (error.code === 401) {
    console.error('Invalid API key')
  } else if (error.code === 408) {
    console.error('Request timeout - try again')
  }
}

API Key Validation

Verify your API key:

try {
  const isValid = await client.validateApiKey()
  if (isValid) {
    console.log('API key is valid')
  } else {
    console.error('Invalid API key')
  }
} catch (error) {
  console.error('Could not validate API key:', error.message)
}

πŸ› οΈ Utilities

The SDK includes helpful utilities for common tasks:

import { 
  formatCoordinates, 
  calculateDistance, 
  getBestResult, 
  isWithinBounds,
  COUNTRY_CODES,
  LANGUAGE_CODES 
} from '@geonot/javascript-sdk'

// Format coordinates for display
const formatted = formatCoordinates(40.7128, -74.0060, 4) // "40.7128, -74.0060"

// Calculate distance between points (in kilometers)
const distance = calculateDistance(40.7128, -74.0060, 34.0522, -118.2437) // ~3944 km

// Get best result from multiple results
const best = getBestResult(results) // Returns result with highest confidence

// Check if coordinates are within bounds
const inBounds = isWithinBounds(40.7128, -74.0060, [40, -75, 41, -73]) // true

// Use predefined constants
const result = await client.geocode({
  query: 'Berlin',
  country: COUNTRY_CODES.DE,
  language: LANGUAGE_CODES.GERMAN
})

πŸŽ›οΈ Advanced Configuration

Custom HTTP Configuration

const client = new OpenCageClient({
  apiKey: 'YOUR_API_KEY',
  timeout: 15000,           // 15 second timeout
  retryAttempts: 5,         // More aggressive retries
  retryDelay: 2000,         // Longer base delay
  userAgent: 'MyApp/1.0.0'  // Custom user agent
})

Performance Tuning

// High-performance configuration
const client = new OpenCageClient({
  apiKey: 'YOUR_API_KEY',
  cache: true,
  cacheSize: 500,           // Larger cache
  cacheTtl: 600000,         // 10 minute cache
  debounce: 150,            // Faster debouncing
  timeout: 5000             // Aggressive timeout
})

// Low-bandwidth configuration
const client = new OpenCageClient({
  apiKey: 'YOUR_API_KEY',
  timeout: 20000,           // Patient timeout
  retryAttempts: 1,         // Fewer retries
  cache: true,
  cacheSize: 50             // Smaller cache
})

Runtime Configuration Updates

// Update configuration without creating new instance
client.updateOptions({
  timeout: 8000,
  cacheSize: 200,
  debounce: 500
})

// Get current configuration
const config = client.getOptions()
console.log('Current timeout:', config.timeout)

πŸ”§ Browser Compatibility

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+
  • iOS Safari 12+
  • Android Chrome 60+

For older browsers, use the UMD build with appropriate polyfills.

πŸ“Š Bundle Size

  • ES Module: ~8KB gzipped
  • UMD Build: ~10KB gzipped
  • Minified UMD: ~7KB gzipped

🀝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“‹ Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Build the library
npm run build

# Lint code
npm run lint

# Format code
npm run format

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • OpenCage Data for providing the excellent geocoding API
  • Built with modern JavaScript standards and best practices
  • Inspired by the needs of frontend developers working with location data

πŸ“ž Support


Made with ❀️ by Rome Stone

About

OpenCage Geocoding API SDK for javascript

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published