Skip to main content
Glama
mieaa.ts10.4 kB
//------------------------------------------------------------- // FORCE IPv4 DNS //------------------------------------------------------------- import dns from "dns"; dns.setDefaultResultOrder("ipv4first"); // ---------------- TYPES ---------------- export interface MiEAAError { success: false; error: string; } export interface MiEAAJobStart { job_id: string; } export type MiEAAStartResponse = MiEAAError | MiEAAJobStart; // ---------------- ERROR WRAPPER ---------------- export function formatMiEAAError(msg: string): MiEAAError { return { success: false, error: msg }; } // ============================================================= // 1. FETCH CATEGORY NAMES // ============================================================= export async function fetchMiEAACategories( species: string, inputType: string ): Promise<{ ids: string[]; map: Record<number, string> } | MiEAAError> { const url = `https://ccb-compute2.cs.uni-saarland.de/mieaa/api/v1/enrichment_categories/${species}/${inputType}/`; try { const res = await fetch(url); const json: any = await res.json(); if (!res.ok || !json.categories) { return formatMiEAAError("Failed to fetch categories"); } const ids: string[] = json.categories.map((pair: any[]) => pair[0]); const map: Record<number, string> = {}; ids.forEach((id, i) => { map[i + 1] = id; }); return { ids, map }; } catch (err: any) { return formatMiEAAError(`CATEGORY FETCH ERROR: ${err?.message}`); } } // ============================================================= // 2. START MI-EAA JOB // ============================================================= export async function startMiEAAJob( body: any, species: string, input_type: string, analysis_type: string ): Promise<MiEAAStartResponse> { const url = `https://ccb-compute2.cs.uni-saarland.de/mieaa/api/v1/enrichment_analysis/${species}/${input_type}/${analysis_type}/`; try { const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) }); const json: any = await res.json(); if (!res.ok || !json.job_id) { return formatMiEAAError("Failed to start job"); } return { job_id: json.job_id }; } catch (err: any) { return formatMiEAAError(`START FETCH ERROR: ${err?.message}`); } } // ============================================================= // 3. FETCH MI-EAA RESULTS (ORA + GSEA AUTO-DETECT) // ============================================================= export async function fetchMiEAAResults( jobId: string ): Promise<any | MiEAAError> { const url = `https://ccb-compute2.cs.uni-saarland.de/mieaa/api/v1/enrichment_analysis/results/${jobId}/`; const LIMIT = 10; // Poll results for up to 120 seconds for (let attempt = 0; attempt < 120; attempt++) { try { const res = await fetch(url); const raw: any = await res.json(); // Still processing → retry if (Array.isArray(raw) && raw.length === 0) { await new Promise(r => setTimeout(r, 1000)); continue; } // ------------------------------------------------------------ // ORA FORMAT → single flat array of rows // ------------------------------------------------------------ if (Array.isArray(raw)) { const grouped: Record<string, any[]> = {}; for (const row of raw) { if (!Array.isArray(row) || row.length < 9) continue; const category = row[0]; if (!grouped[category]) grouped[category] = []; grouped[category].push({ category: row[0], term: row[1], direction: row[2], p_value: row[3], adj_p_value: row[4], score: row[5], hits: row[7], mirnas: row[8] }); } for (const key of Object.keys(grouped)) { grouped[key] = grouped[key].slice(0, LIMIT); } return grouped; } // ------------------------------------------------------------ // OBJECT FORMAT (ORA or GSEA) // ------------------------------------------------------------ if (typeof raw === "object" && raw !== null) { // WRAPPED GSEA: { Enrichment_Results: {...} } if (raw.Enrichment_Results) { const out: Record<string, any[]> = {}; for (const cat of Object.keys(raw.Enrichment_Results)) { const rows = raw.Enrichment_Results[cat]; if (!Array.isArray(rows)) continue; out[cat] = rows.slice(0, LIMIT).map(r => ({ category: cat, term: r.term ?? r.name ?? "", direction: r.direction ?? "", es: r.es, nes: r.nes, p_value: r.p_value, adj_p_value: r.adj_p_value, leading_edge: r.leading_edge, mirnas: r.mirnas })); } return out; } // UNWRAPPED GSEA: { category: [ {term:...} ] } const looksLikeGSEA = Object.values(raw).some( v => Array.isArray(v) && typeof v[0] === "object" ); const out: Record<string, any[]> = {}; for (const cat of Object.keys(raw)) { const rows = raw[cat]; if (!Array.isArray(rows)) continue; // GSEA object rows if (looksLikeGSEA && typeof rows[0] === "object") { out[cat] = rows.slice(0, LIMIT).map(r => ({ category: cat, term: r.term ?? r.name ?? "", direction: r.direction ?? "", es: r.es, nes: r.nes, p_value: r.p_value, adj_p_value: r.adj_p_value, leading_edge: r.leading_edge, mirnas: r.mirnas })); } // ORA object-format rows else { out[cat] = rows.slice(0, LIMIT).map(row => ({ category: row[0], term: row[1], direction: row[2], p_value: row[3], adj_p_value: row[4], score: row[5], hits: row[7], mirnas: row[8] })); } } return out; } } catch { // ignore errors and retry } await new Promise(r => setTimeout(r, 1000)); } return formatMiEAAError("Timeout: results never became available."); } // ============================================================= // 4. LIST ENRICHMENT CATEGORIES (DISCOVERY TOOL) // ============================================================= export async function listMiEAACategories( species: string, entity: "mirna" | "precursor" ): Promise<any | MiEAAError> { const url = `https://ccb-compute2.cs.uni-saarland.de/mieaa/api/v1/enrichment_categories/${species}/${entity}/`; try { const res = await fetch(url); const json: any = await res.json(); if (!res.ok) { return formatMiEAAError("Failed to list enrichment categories"); } if (!Array.isArray(json.categories)) { return formatMiEAAError("Invalid category response format"); } return { species, entity, categories: json.categories.map((c: any, idx: number) => ({ index: idx + 1, id: c[0], name: c[1] })) }; } catch (err: any) { return formatMiEAAError(`CATEGORY LIST ERROR: ${err?.message}`); } } // ============================================================= // 5. miRBASE VERSION CONVERTER // ============================================================= export async function convertMiRBaseVersion(args: { mirnas: string[]; from_version: string; to_version: string; }): Promise<any | MiEAAError> { const url = "https://ccb-compute2.cs.uni-saarland.de/mieaa/api/v1/mirbase_converter/"; try { const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(args) }); const json = await res.json(); if (!res.ok) { return formatMiEAAError("miRBase conversion failed"); } return json; } catch (err: any) { return formatMiEAAError(`MIRBASE CONVERTER ERROR: ${err?.message}`); } } // ============================================================= // 6. miRNA ↔ PRECURSOR CONVERTER // ============================================================= export async function convertMirnaPrecursor(args: { input: string[]; direction: "mirna_to_precursor" | "precursor_to_mirna"; }): Promise<any | MiEAAError> { const url = "https://ccb-compute2.cs.uni-saarland.de/mieaa/api/v1/mirna_precursor_converter/"; try { const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(args) }); const json = await res.json(); if (!res.ok) { return formatMiEAAError("miRNA/Precursor conversion failed"); } return json; } catch (err: any) { return formatMiEAAError(`CONVERTER ERROR: ${err?.message}`); } } // ============================================================= // 7. FETCH JOB STATUS // ============================================================= export async function fetchMiEAAJobStatus( jobId: string ): Promise<any | MiEAAError> { const url = `https://ccb-compute2.cs.uni-saarland.de/mieaa/api/v1/job_status/${jobId}/`; try { const res = await fetch(url); const json = await res.json(); if (!res.ok) { return formatMiEAAError("Failed to fetch job status"); } return json; } catch (err: any) { return formatMiEAAError(`JOB STATUS ERROR: ${err?.message}`); } } // ============================================================= // 8. FETCH JOB RESULTS (DIRECT) // ============================================================= export async function fetchMiEAAJobResultsDirect( jobId: string ): Promise<any | MiEAAError> { const url = `https://ccb-compute2.cs.uni-saarland.de/mieaa/api/v1/enrichment_analysis/results/${jobId}/`; try { const res = await fetch(url); const json = await res.json(); if (!res.ok) { return formatMiEAAError("Failed to fetch job results"); } return json; } catch (err: any) { return formatMiEAAError(`JOB RESULT ERROR: ${err?.message}`); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kkShrihari/miEAA3_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server