const query = ` [out:json][timeout:120]; area["ISO3166-2"="US-CA"][admin_level=4]->.searchArea; ( node["amenity"="fast_food"]["brand"="In-N-Out Burger"](area.searchArea); way["amenity"="fast_food"]["brand"="In-N-Out Burger"](area.searchArea); relation["amenity"="fast_food"]["brand"="In-N-Out Burger"](area.searchArea); node["amenity"="fast_food"]["name"~"In-N-Out",i](area.searchArea); way["amenity"="fast_food"]["name"~"In-N-Out",i](area.searchArea); relation["amenity"="fast_food"]["name"~"In-N-Out",i](area.searchArea); ); out center tags; `; function normalizeStores(elements) { const stores = elements .map((element) => { const lat = Number(element.lat ?? element.center?.lat); const lon = Number(element.lon ?? element.center?.lon); if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null; const tags = element.tags ?? {}; const name = tags.name || "In-N-Out Burger"; const city = tags["addr:city"] || "Ville inconnue"; const street = tags["addr:street"] || ""; const housenumber = tags["addr:housenumber"] || ""; const postcode = tags["addr:postcode"] || ""; return { id: `${element.type}/${element.id}`, latitude: lat, longitude: lon, name, city, address: [housenumber, street].filter(Boolean).join(" "), postcode, }; }) .filter(Boolean); const dedup = new Map(); for (const store of stores) { const key = `${store.latitude.toFixed(5)},${store.longitude.toFixed(5)}`; if (!dedup.has(key)) dedup.set(key, store); } return Array.from(dedup.values()); } async function fetchFromOverpass() { const endpoints = [ "https://overpass-api.de/api/interpreter", "https://overpass.kumi.systems/api/interpreter", "https://overpass.openstreetmap.fr/api/interpreter", ]; for (const endpoint of endpoints) { try { const response = await fetch(endpoint, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded;charset=UTF-8", }, body: new URLSearchParams({ data: query }), }); if (!response.ok) continue; const payload = await response.json(); const elements = Array.isArray(payload.elements) ? payload.elements : []; const stores = normalizeStores(elements); if (stores.length >= 50) return stores; } catch {} } return null; } async function fetchFallbackCsv() { const url = "https://raw.githubusercontent.com/madmao/castle-compass/master/csv/In%20N%20Out.csv"; const response = await fetch(url); if (!response.ok) throw new Error(`Fallback CSV request failed: ${response.status}`); const lines = (await response.text()).split(/\r?\n/).filter(Boolean); const stores = lines .map((line, index) => { const [latRaw, lonRaw] = line.split(","); const latitude = Number(latRaw); const longitude = Number(lonRaw); if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) return null; const inCaliforniaBounds = latitude >= 32 && latitude <= 42.5 && longitude >= -125 && longitude <= -114; if (!inCaliforniaBounds) return null; return { id: `fallback/${index}`, latitude, longitude, name: "In-N-Out Burger", city: "Ville inconnue", address: "", postcode: "", }; }) .filter(Boolean); return stores; } const stores = (await fetchFromOverpass()) ?? (await fetchFallbackCsv()); process.stdout.write(JSON.stringify(stores));