first commit

This commit is contained in:
lendry
2026-06-24 14:37:15 +03:00
commit 995adeedd4
188 changed files with 28810 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
export interface ParsedAddress {
city: string;
street: string;
house: string;
fullAddress: string;
}
const NOMINATIM_HEADERS = {
'User-Agent': 'LendryID/1.0 (contact@lendry.ru)',
Accept: 'application/json'
};
export async function reverseGeocode(lat: number, lng: number): Promise<ParsedAddress | null> {
try {
const url = `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${encodeURIComponent(String(lat))}&lon=${encodeURIComponent(String(lng))}&accept-language=ru`;
const response = await fetch(url, { headers: NOMINATIM_HEADERS });
if (!response.ok) return null;
const data = (await response.json()) as {
display_name?: string;
address?: Record<string, string | undefined>;
};
const addr = data.address ?? {};
const city = addr.city || addr.town || addr.village || addr.municipality || addr.state || '';
const street = addr.road || addr.pedestrian || addr.footway || addr.neighbourhood || '';
const house = addr.house_number || '';
return {
city,
street,
house,
fullAddress: data.display_name ?? formatParsed(city, street, house)
};
} catch {
return null;
}
}
export async function forwardGeocode(query: string): Promise<{ lat: number; lng: number; parsed: ParsedAddress } | null> {
const trimmed = query.trim();
if (!trimmed) return null;
try {
const url = `https://nominatim.openstreetmap.org/search?format=jsonv2&q=${encodeURIComponent(trimmed)}&limit=1&accept-language=ru`;
const response = await fetch(url, { headers: NOMINATIM_HEADERS });
if (!response.ok) return null;
const data = (await response.json()) as Array<{
lat: string;
lon: string;
display_name?: string;
address?: Record<string, string | undefined>;
}>;
const first = data[0];
if (!first) return null;
const addr = first.address ?? {};
const city = addr.city || addr.town || addr.village || addr.municipality || '';
const street = addr.road || addr.pedestrian || '';
const house = addr.house_number || '';
return {
lat: Number(first.lat),
lng: Number(first.lon),
parsed: {
city,
street,
house,
fullAddress: first.display_name ?? formatParsed(city, street, house)
}
};
} catch {
return null;
}
}
function formatParsed(city: string, street: string, house: string) {
const parts = [];
if (city) parts.push(`г. ${city}`);
if (street || house) parts.push([street, house].filter(Boolean).join(', '));
return parts.join(', ');
}