Overview
The geolocation API provides functions to automatically detect a user’s location or resolve city/country queries. These functions are useful for providing location-based defaults in your application.
Auto-detect Location
guessLocation
Automatically detect the user’s location based on their IP address.
import { guessLocation } from 'ramadan-cli' ;
const location = await guessLocation ();
if ( location ) {
console . log ( location . city ); // "Lahore"
console . log ( location . country ); // "Pakistan"
console . log ( location . latitude ); // 31.5204
console . log ( location . longitude ); // 74.3587
console . log ( location . timezone ); // "Asia/Karachi"
}
return
Promise<GeoLocation | null>
Location data or null if detection fails IANA timezone string (e.g., “Asia/Karachi”)
How It Works
The guessLocation function tries multiple free IP geolocation services in sequence:
ip-api.com - First attempt
ipapi.co - Fallback if first fails
ipwho.is - Final fallback
This redundancy ensures high reliability even if one service is down.
IP-based geolocation may not be accurate for users behind VPNs or proxies.
Resolve City Query
guessCityCountry
Resolve a city name or query string to get coordinates and timezone.
import { guessCityCountry } from 'ramadan-cli' ;
const result = await guessCityCountry ( 'Istanbul' );
if ( result ) {
console . log ( result . city ); // "Istanbul"
console . log ( result . country ); // "Turkey"
console . log ( result . latitude ); // 41.0082
console . log ( result . longitude ); // 28.9784
console . log ( result . timezone ); // "Europe/Istanbul"
}
City name or search query (e.g., “London”, “New York”, “Tokyo”)
return
Promise<CityCountryGuess | null>
City data or null if not found IANA timezone string (may be undefined)
Geocoding Service
This function uses the Open-Meteo Geocoding API to resolve city queries. The API:
Returns the first (most relevant) match for ambiguous queries
Supports international city names
Provides accurate coordinates and timezone data
Is free and requires no API key
Usage Examples
Auto-detect and Save Location
import { guessLocation , saveAutoDetectedSetup } from 'ramadan-cli' ;
const location = await guessLocation ();
if ( location ) {
// Save location to config
saveAutoDetectedSetup ( location );
console . log ( `Location saved: ${ location . city } , ${ location . country } ` );
} else {
console . log ( 'Could not detect location' );
}
Search for City
import { guessCityCountry } from 'ramadan-cli' ;
// Search with various formats
const queries = [
'Paris' ,
'San Francisco' ,
'Dubai' ,
'New York City' ,
];
for ( const query of queries ) {
const result = await guessCityCountry ( query );
if ( result ) {
console . log ( ` ${ query } → ${ result . city } , ${ result . country } ` );
console . log ( ` Coordinates: ${ result . latitude } , ${ result . longitude } ` );
console . log ( ` Timezone: ${ result . timezone } ` );
} else {
console . log ( ` ${ query } → Not found` );
}
}
Fallback Chain
import { guessLocation , guessCityCountry } from 'ramadan-cli' ;
// Try auto-detect first, then fallback to manual search
let location = await guessLocation ();
if ( ! location ) {
console . log ( 'Auto-detect failed, trying manual search...' );
location = await guessCityCountry ( 'London' );
}
if ( location ) {
console . log ( `Using: ${ location . city } , ${ location . country } ` );
} else {
console . log ( 'No location available' );
}
import { guessCityCountry } from 'ramadan-cli' ;
async function validateCity ( userInput : string ) : Promise < boolean > {
const result = await guessCityCountry ( userInput );
return result !== null ;
}
const isValid = await validateCity ( 'Tokyo' );
if ( isValid ) {
console . log ( 'Valid city' );
} else {
console . log ( 'City not found' );
}
Get Timezone for Prayer Times
import { guessCityCountry , fetchTimingsByCoords } from 'ramadan-cli' ;
const cityData = await guessCityCountry ( 'Jakarta' );
if ( cityData && cityData . timezone ) {
const prayerTimes = await fetchTimingsByCoords ({
latitude: cityData . latitude ,
longitude: cityData . longitude ,
timezone: cityData . timezone , // Use resolved timezone
method: 20 , // Indonesia method
});
console . log ( prayerTimes . timings );
}
Integration with Prayer Times API
import {
guessLocation ,
guessCityCountry ,
fetchTimingsByCity ,
fetchTimingsByCoords ,
} from 'ramadan-cli' ;
// Auto-detect and fetch prayer times
const location = await guessLocation ();
if ( location ) {
const prayerTimes = await fetchTimingsByCity ({
city: location . city ,
country: location . country ,
method: 2 ,
});
console . log ( 'Fajr:' , prayerTimes . timings . Fajr );
}
// Or resolve city name and use coordinates
const cityData = await guessCityCountry ( 'Cairo' );
if ( cityData ) {
const prayerTimes = await fetchTimingsByCoords ({
latitude: cityData . latitude ,
longitude: cityData . longitude ,
timezone: cityData . timezone ,
method: 5 , // Egypt method
});
console . log ( 'Maghrib:' , prayerTimes . timings . Maghrib );
}
Error Handling
Both functions return null on failure rather than throwing errors. Always check the return value:
import { guessLocation } from 'ramadan-cli' ;
const location = await guessLocation ();
if ( ! location ) {
console . error ( 'Failed to detect location' );
// Handle error: prompt user, use default, etc.
return ;
}
// Safe to use location here
console . log ( location . city );
TypeScript Types
interface GeoLocation {
readonly city : string ;
readonly country : string ;
readonly latitude : number ;
readonly longitude : number ;
readonly timezone : string ;
}
interface CityCountryGuess {
readonly city : string ;
readonly country : string ;
readonly latitude : number ;
readonly longitude : number ;
readonly timezone ?: string ; // May be undefined
}
Privacy Considerations
IP geolocation APIs typically collect:
User’s IP address
Request timestamp
User agent information
No personal data is sent by ramadan-cli. Users behind VPNs or proxies will see the VPN/proxy location.
guessLocation: ~500ms (tries up to 3 services)
guessCityCountry: ~200ms (single API call)
Consider caching results to avoid repeated lookups:
import { guessLocation } from 'ramadan-cli' ;
let cachedLocation : Awaited < ReturnType < typeof guessLocation >> | null = null ;
async function getLocation () {
if ( ! cachedLocation ) {
cachedLocation = await guessLocation ();
}
return cachedLocation ;
}