A tonne more changes, including new nocodb admin section, search for database, code cleanups, and debugging

This commit is contained in:
2025-08-01 15:01:35 -06:00
parent 9fcaf4823f
commit 5b673dacc2
18 changed files with 2780 additions and 114 deletions

View File

@@ -95,6 +95,78 @@ async function reverseGeocode(lat, lng) {
}
}
/**
* Forward geocode address to get coordinates (for search - returns multiple results)
* @param {string} address - Address to search
* @param {number} limit - Maximum number of results to return
* @returns {Promise<Array>} Array of geocoding results
*/
async function forwardGeocodeSearch(address, limit = 5) {
// Create cache key
const cacheKey = `search:${address.toLowerCase()}:${limit}`;
// Check cache first
const cached = geocodeCache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
logger.debug(`Geocoding search cache hit for ${cacheKey}`);
return cached.data;
}
try {
// Add delay to respect rate limits
await new Promise(resolve => setTimeout(resolve, 1000));
logger.info(`Forward geocoding search: ${address}`);
const response = await axios.get('https://nominatim.openstreetmap.org/search', {
params: {
format: 'json',
q: address,
limit: limit,
addressdetails: 1,
'accept-language': 'en',
countrycodes: 'ca' // Limit to Canada for this application
},
headers: {
'User-Agent': 'NocoDB Map Viewer 1.0 (contact@example.com)'
},
timeout: 15000
});
if (!response.data || response.data.length === 0) {
return [];
}
// Process all results
const results = response.data.map(item => processGeocodeResponse(item));
// Cache the results
geocodeCache.set(cacheKey, {
data: results,
timestamp: Date.now()
});
return results;
} catch (error) {
logger.error('Forward geocoding search error:', error.message);
if (error.response?.status === 429) {
throw new Error('Rate limit exceeded. Please try again later.');
} else if (error.response?.status === 403) {
throw new Error('Access denied by geocoding service');
} else if (error.response?.status === 500) {
throw new Error('Geocoding service internal error');
} else if (error.code === 'ECONNABORTED') {
throw new Error('Geocoding request timeout');
} else if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') {
throw new Error('Cannot connect to geocoding service');
} else {
throw new Error(`Geocoding search failed: ${error.message}`);
}
}
}
/**
* Forward geocode address to get coordinates
* @param {string} address - Address to geocode
@@ -202,6 +274,9 @@ function processGeocodeResponse(data) {
lat: parseFloat(data.lat),
lng: parseFloat(data.lon)
},
// Backward compatibility
latitude: parseFloat(data.lat),
longitude: parseFloat(data.lon),
boundingBox: data.boundingbox || null,
placeId: data.place_id || null,
osmType: data.osm_type || null,
@@ -232,6 +307,7 @@ function clearCache() {
module.exports = {
reverseGeocode,
forwardGeocode,
forwardGeocodeSearch,
getCacheStats,
clearCache
};