import { fetchIt, getConfig } from "./imports"; let _baseUrl: string | null = null; let _endpointMap: Record | null = null; function joinApi(base: string, slug: string): string { return `${base}/${slug}`.replace(/\/api\/api\//, '/api/'); } /** * Get your API’s base URL from config, or fall back */ export async function getBaseUrl(key = 'BASE_API_URL'): Promise { try { const url = await getConfig(key as any); // if the config var is missing or empty, fall back if (!url || typeof url !== 'string') { console.warn(`Config var ${key} is unset; using default`); return 'https://api.abstractendeavors.com'; } return url.replace(/\/+$/, ''); // trim trailing slash } catch (err) { console.warn(`Error fetching config var ${key}; using default`, err); return 'https://api.abstractendeavors.com'; } } /** Ensure we only fetch the base URL once */ async function _getBaseUrl(): Promise { if (_baseUrl) return _baseUrl; try { const raw = await getConfig('BASE_API_URL'); const clean = (raw && typeof raw === 'string') ? raw.replace(/\/+$/, '') : 'https://api.abstractendeavors.com'; _baseUrl = clean; } catch { _baseUrl = 'https://api.abstractendeavors.com'; } return _baseUrl; } /** * Always resolves a usable base URL: config or default */ export async function getUrl(base_url?: string | null): Promise { if (base_url && typeof base_url === 'string') { return base_url.replace(/\/+$/, ''); } return await getBaseUrl(); } /** * Fetch the endpoints list */ export async function getEndpoints(base_url?: string | null): Promise { const url = await getUrl(base_url); const endpointsUrl = `${url}/endpoints`; return await fetchIt(endpointsUrl, {}, 'GET'); } /** Ensure we only fetch & map endpoints once */ export async function getUrls(): Promise> { if (_endpointMap) return _endpointMap; const base = await _getBaseUrl(); const endpoints: Array<[string, any]> = await fetchIt( `${base}/endpoints`, {}, 'GET' ); // build slug → full URL map _endpointMap = endpoints.reduce((map, [path]) => { let slug = path.replace(/^\/+/, ''); // remove leading slashes // normalize: remove a leading "api/" if (slug.startsWith("api/")) { slug = slug.slice(4); } // now always join with base (which already ends with /api) map[slug] = joinApi(base, slug); return map; }, {} as Record); return _endpointMap; } /** * Find the best‐match endpoint slug under your API */ export async function getEndpoint(keyword: string): Promise { const lower = keyword.toLowerCase(); const urls = await getUrls(); let best: [string, string] | null = null; for (const [slug, fullUrl] of Object.entries(urls)) { if (slug.toLowerCase().includes(lower)) { if (!best || slug.length > best[0].length) { best = [slug, fullUrl]; } } } if (!best) { const base = await _getBaseUrl(); throw new Error(`No endpoint matching “${keyword}” under ${base}`); } return best[1]; }