UNPKG

fetchbee

Version:

A lightweight JS library to simplify all kinds of API calls.

194 lines (161 loc) 6.72 kB
const fallbackBaseUrl = "https://jsonplaceholder.typicode.com/posts"; function createInput(labelText, placeholder = "", type = "text") { const wrapper = document.createElement("div"); wrapper.style.marginBottom = "12px"; const label = document.createElement("label"); label.textContent = labelText; label.style.display = "block"; label.style.marginBottom = "4px"; label.style.fontWeight = "bold"; const input = document.createElement("input"); input.placeholder = placeholder; input.type = type; input.style.width = "100%"; input.style.padding = "6px"; input.style.border = "1px solid #ccc"; input.style.borderRadius = "4px"; wrapper.appendChild(label); wrapper.appendChild(input); return { wrapper, input }; } function createApiTesterUI() { const brandColor = "#f1c40f"; document.body.style.fontFamily = "Segoe UI, sans-serif"; document.body.style.margin = "0"; document.body.style.background = "#fff8dc"; const title = document.createElement("h1"); title.textContent = "🐝 FetchBee API Tester"; title.style.color = "#222"; title.style.background = brandColor; title.style.padding = "16px"; title.style.textAlign = "center"; title.style.margin = "0"; title.style.boxShadow = "0 2px 6px rgba(0,0,0,0.1)"; document.body.prepend(title); const container = document.createElement("div"); container.style.display = "flex"; container.style.maxWidth = "1100px"; container.style.margin = "30px auto"; container.style.border = `2px solid ${brandColor}`; container.style.borderRadius = "12px"; container.style.overflow = "hidden"; container.style.boxShadow = "0 0 8px rgba(0,0,0,0.1)"; container.style.gap = "0"; // even spacing const left = document.createElement("div"); left.style.flex = "3"; // 30% left.style.padding = "20px"; left.style.background = "#fffef3"; left.style.borderRight = "1px solid #eee"; const right = document.createElement("div"); right.style.flex = "6"; // 60% right.style.padding = "20px"; right.style.background = "#ffffff"; right.style.overflow = "scroll"; const { wrapper: baseUrlWrap, input: baseUrlInput } = createInput("API Base URL", fallbackBaseUrl); const { wrapper: idWrap, input: idInput } = createInput("ID (optional)"); const { wrapper: searchWrap, input: searchInput } = createInput("Search (optional)"); const { wrapper: fromWrap, input: fromInput } = createInput("From Date", "", "date"); const { wrapper: toWrap, input: toInput } = createInput("To Date", "", "date"); const { wrapper: pageWrap, input: pageInput } = createInput("Page", "1", "number"); const { wrapper: sizeWrap, input: sizeInput } = createInput("Size", "10", "number"); const { wrapper: tokenWrap, input: tokenInput } = createInput("Auth Token"); [baseUrlWrap, idWrap, searchWrap, fromWrap, toWrap, pageWrap, sizeWrap, tokenWrap].forEach(i => left.appendChild(i)); const bodyLabel = document.createElement("label"); bodyLabel.textContent = "Request Body (for POST / PUT / PATCH)"; bodyLabel.style.fontWeight = "bold"; const bodyInput = document.createElement("textarea"); bodyInput.style.width = "100%"; bodyInput.style.height = "120px"; bodyInput.style.marginTop = "6px"; bodyInput.style.padding = "8px"; bodyInput.style.border = "1px solid #ccc"; bodyInput.style.borderRadius = "4px"; bodyInput.placeholder = `{\n "title": "example",\n "body": "sample",\n "userId": 1\n}`; right.appendChild(bodyLabel); right.appendChild(bodyInput); const buttonGroup = document.createElement("div"); buttonGroup.style.marginTop = "16px"; const errorEl = document.createElement("p"); errorEl.style.color = "red"; const responseEl = document.createElement("pre"); responseEl.style.marginTop = "20px"; responseEl.style.background = "#fdf8e4"; responseEl.style.border = "1px solid #ddd"; responseEl.style.padding = "16px"; responseEl.style.borderRadius = "6px"; responseEl.style.maxHeight = "400px"; responseEl.style.overflow = "auto"; const methods = ["GET", "POST", "PUT", "PATCH", "DELETE"]; methods.forEach((method) => { const btn = document.createElement("button"); btn.textContent = method; btn.style.background = brandColor; btn.style.color = "#000"; btn.style.border = "none"; btn.style.padding = "10px 18px"; btn.style.marginRight = "10px"; btn.style.marginTop = "10px"; btn.style.borderRadius = "4px"; btn.style.cursor = "pointer"; btn.style.fontWeight = "bold"; btn.onclick = async () => { errorEl.textContent = ""; responseEl.textContent = "⏳ Loading..."; const baseUrl = baseUrlInput.value.trim() || fallbackBaseUrl; const id = idInput.value.trim(); const url = id ? `${baseUrl}/${id}` : baseUrl; const query = {}; if (searchInput.value) query.search = searchInput.value.trim(); if (fromInput.value) query.from = fromInput.value; if (toInput.value) query.to = toInput.value; if (pageInput.value) query.page = Number(pageInput.value); if (sizeInput.value) query.size = Number(sizeInput.value); const headers = {}; if (tokenInput.value.trim()) { headers.Authorization = `Bearer ${tokenInput.value.trim()}`; } let body = {}; if (["POST", "PUT", "PATCH"].includes(method)) { try { body = JSON.parse(bodyInput.value || "{}"); } catch (e) { errorEl.textContent = "Invalid JSON in request body."; responseEl.textContent = ""; return; } } try { const response = await fetchBeeRequest(method, url, body, query, headers); responseEl.textContent = JSON.stringify(response, null, 2); } catch (err) { errorEl.textContent = err.message; responseEl.textContent = ""; } }; buttonGroup.appendChild(btn); }); right.appendChild(buttonGroup); right.appendChild(errorEl); right.appendChild(responseEl); container.appendChild(left); container.appendChild(right); document.body.appendChild(container); } async function fetchBeeRequest(method, url, body = {}, query = {}, headers = {}) { const queryString = new URLSearchParams(query).toString(); const fullUrl = queryString ? `${url}?${queryString}` : url; const fetchOptions = { method, headers: { 'Content-Type': 'application/json', ...headers, }, }; if (["POST", "PUT", "PATCH"].includes(method)) { fetchOptions.body = JSON.stringify(body); } const response = await fetch(fullUrl, fetchOptions); if (!response.ok) throw new Error(`${method} failed with status ${response.status}`); return await response.json(); } window.onload = createApiTesterUI;