Hey there, fellow JavaScript devs! Ready to dive into the world of GitHub API integration? Let's explore how to sync data for user-facing integrations using GitHub's powerful API. Buckle up, because we're about to make your apps a whole lot cooler!
First things first, let's get you set up. You'll need to authenticate with GitHub, and trust me, it's easier than trying to explain why you have 50 unresolved Git conflicts. We'll use OAuth or Personal Access Tokens - pick your poison.
Install Octokit.js, our trusty sidekick for this adventure:
npm install @octokit/rest
Now, let's initialize it:
import { Octokit } from "@octokit/rest"; const octokit = new Octokit({ auth: 'your-token-here' });
Want to fetch user info? Repo data? Issues and PRs? GitHub's got you covered. Here's a quick example of how to fetch and cache user repos:
async function getUserRepos(username) { const cacheKey = `repos_${username}`; const cachedData = localStorage.getItem(cacheKey); if (cachedData) { return JSON.parse(cachedData); } const { data } = await octokit.repos.listForUser({ username }); localStorage.setItem(cacheKey, JSON.stringify(data)); return data; }
Creating files, updating repos, managing issues - it's all possible. Here's how you can update a file:
async function updateFile(owner, repo, path, content, sha) { await octokit.repos.createOrUpdateFileContents({ owner, repo, path, message: 'Update file via API', content: Buffer.from(content).toString('base64'), sha }); }
For real-time updates, webhooks are your best friend. Here's a simple Express server to listen for webhook events:
import express from 'express'; const app = express(); app.use(express.json()); app.post('/webhook', (req, res) => { const event = req.headers['x-github-event']; const payload = req.body; console.log(`Received ${event} event:`, payload); // Handle the event here res.sendStatus(200); }); app.listen(3000, () => console.log('Webhook listener running on port 3000'));
Let's implement conditional requests to save bandwidth and stay on GitHub's good side:
async function getRepoWithETag(owner, repo) { const cacheKey = `repo_${owner}_${repo}`; const cachedData = localStorage.getItem(cacheKey); const cachedETag = localStorage.getItem(`${cacheKey}_etag`); try { const { data, headers } = await octokit.repos.get({ owner, repo, headers: cachedETag ? { 'If-None-Match': cachedETag } : {} }); if (headers.etag) { localStorage.setItem(cacheKey, JSON.stringify(data)); localStorage.setItem(`${cacheKey}_etag`, headers.etag); } return data; } catch (error) { if (error.status === 304) { return JSON.parse(cachedData); } throw error; } }
Even the best of us face errors. Here's how to handle them gracefully:
async function safeApiCall(apiFunction, ...args) { try { return await apiFunction(...args); } catch (error) { if (error.status === 403 && error.headers['x-ratelimit-remaining'] === '0') { console.log('Rate limit exceeded. Retrying after cooldown...'); const resetTime = error.headers['x-ratelimit-reset'] * 1000; await new Promise(resolve => setTimeout(resolve, resetTime - Date.now())); return safeApiCall(apiFunction, ...args); } console.error('API call failed:', error); throw error; } }
And there you have it! You're now equipped to read and write data like a GitHub API ninja. Remember to keep your API calls to a minimum, secure that user data, and always follow GitHub's usage guidelines.
Keep coding, keep learning, and may your pull requests always be conflict-free!