Project Files
src / search / searxng.ts
/**
* searxng.ts — legacy-compatible search entry point backed by SearXNG.
* Drop-in replacement for the old duckduckgo.ts search function.
*/
import { SearXNGProvider } from "./providers/SearXNGProvider";
import { SEARXNG_BASE_URL } from "../utils/constants";
// =============================================================
// 💾 IN-MEMORY CACHE (mirrors old duckduckgo.ts behaviour)
// =============================================================
interface CachedResult {
value: Promise<string[]>;
expiresAt: number;
}
const searchCache = new Map<string, CachedResult>();
const CACHE_TTL_MS = 30 * 60 * 1000; // 30 minutes
function getCachedResults(query: string): Promise<string[]> | null {
const entry = searchCache.get(query);
if (!entry) return null;
if (Date.now() >= entry.expiresAt) {
searchCache.delete(query);
return null;
}
return entry.value;
}
function setCache(query: string, promise: Promise<string[]>): void {
searchCache.set(query, { value: promise, expiresAt: Date.now() + CACHE_TTL_MS });
}
// =============================================================
// 🔎 CORE FUNCTION: searchSearXNG
// =============================================================
/**
* Searches via a SearXNG instance.
* @param query The search term.
* @param baseUrl Override the SearXNG base URL (defaults to SEARXNG_BASE_URL constant).
*/
export async function searchSearXNG(
query: string,
baseUrl: string = SEARXNG_BASE_URL
): Promise<string[]> {
const cached = getCachedResults(query);
if (cached) {
console.log(`\n============================================`);
console.log(`[CACHE HIT] Returning cached results for: ${query}`);
console.log(`============================================`);
return cached;
}
console.log(`\n============================================`);
console.log(`[INFO] Starting SearXNG search for "${query}" at ${baseUrl}`);
console.log(`============================================`);
try {
const provider = new SearXNGProvider(baseUrl);
const resultPromise = provider.search(query);
setCache(query, resultPromise);
const urls = await resultPromise;
console.log(`[SUCCESS] Found ${urls.length} unique URLs.`);
return urls;
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error";
throw new Error(
`[SEARCH FAILURE] SearXNG could not retrieve URLs for "${query}". Reason: ${message}`
);
}
}