Back

Reading and Writing Data Using the GitHub API

Aug 2, 20246 minute read

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!

Setting the Stage

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' });

Reading from GitHub: It's Like Mind Reading, But Cooler

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; }

Writing to GitHub: Leave Your Mark

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 }); }

Syncing Data: Real-time Magic

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'));

Optimizing Your Sync: Work Smarter, Not Harder

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; } }

Handling Errors Like a Pro

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; } }

Wrapping Up

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!