mirror of
				https://github.com/jakejarvis/jarv.is.git
				synced 2025-10-31 03:56:03 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			107 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import * as Sentry from "@sentry/node";
 | |
| import { graphql } from "@octokit/graphql";
 | |
| 
 | |
| Sentry.init({
 | |
|   dsn: process.env.SENTRY_DSN || "",
 | |
|   environment: process.env.NODE_ENV || process.env.VERCEL_ENV || "",
 | |
| });
 | |
| 
 | |
| export default async (req, res) => {
 | |
|   try {
 | |
|     // some rudimentary error handling
 | |
|     if (req.method !== "GET") {
 | |
|       throw new Error(`Method ${req.method} not allowed.`);
 | |
|     }
 | |
|     if (!process.env.GH_PUBLIC_TOKEN) {
 | |
|       throw new Error("GitHub API credentials aren't set.");
 | |
|     }
 | |
| 
 | |
|     // allow custom limit, max. 24 results
 | |
|     let limit = 24;
 | |
|     if (req.query.limit && req.query.limit > 0 && req.query.limit < limit) {
 | |
|       limit = req.query.limit;
 | |
|     }
 | |
| 
 | |
|     let result;
 | |
|     if (typeof req.query.top !== "undefined") {
 | |
|       // get most popular repos (/projects/?top)
 | |
|       result = await fetchRepos("STARGAZERS", limit);
 | |
|     } else {
 | |
|       // default to latest repos
 | |
|       result = await fetchRepos("PUSHED_AT", limit);
 | |
|     }
 | |
| 
 | |
|     // let Vercel edge and browser cache results for 15 mins
 | |
|     res.setHeader("Cache-Control", "public, max-age=900, s-maxage=900, stale-while-revalidate");
 | |
|     res.setHeader("Access-Control-Allow-Methods", "GET");
 | |
|     res.setHeader("Access-Control-Allow-Origin", "*");
 | |
| 
 | |
|     res.status(200).json(result);
 | |
|   } catch (error) {
 | |
|     console.error(error);
 | |
| 
 | |
|     // log error to sentry, give it 2 seconds to finish sending
 | |
|     Sentry.captureException(error);
 | |
|     await Sentry.flush(2000);
 | |
| 
 | |
|     const message = error instanceof Error ? error.message : "Unknown error.";
 | |
| 
 | |
|     res.status(400).json({ success: false, message: message });
 | |
|   }
 | |
| };
 | |
| 
 | |
| const fetchRepos = async (sort, limit) => {
 | |
|   // https://docs.github.com/en/graphql/reference/objects#repository
 | |
|   const { user } = await graphql(
 | |
|     `
 | |
|       query ($username: String!, $sort: String, $limit: Int) {
 | |
|         user(login: $username) {
 | |
|           repositories(
 | |
|             first: $limit
 | |
|             isLocked: false
 | |
|             isFork: false
 | |
|             ownerAffiliations: OWNER
 | |
|             privacy: PUBLIC
 | |
|             orderBy: { field: $sort, direction: DESC }
 | |
|           ) {
 | |
|             edges {
 | |
|               node {
 | |
|                 name
 | |
|                 url
 | |
|                 description
 | |
|                 pushedAt
 | |
|                 stargazerCount
 | |
|                 forkCount
 | |
|                 primaryLanguage {
 | |
|                   name
 | |
|                   color
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     `,
 | |
|     {
 | |
|       username: "jakejarvis",
 | |
|       limit: parseInt(limit),
 | |
|       sort: sort,
 | |
|       headers: {
 | |
|         authorization: `token ${process.env.GH_PUBLIC_TOKEN}`,
 | |
|       },
 | |
|     }
 | |
|   );
 | |
| 
 | |
|   const repos = user.repositories.edges.map(({ node: repo }) => ({
 | |
|     name: repo.name,
 | |
|     url: repo.url,
 | |
|     description: repo.description,
 | |
|     updatedAt: new Date(repo.pushedAt),
 | |
|     stars: repo.stargazerCount,
 | |
|     forks: repo.forkCount,
 | |
|     language: repo.primaryLanguage,
 | |
|   }));
 | |
| 
 | |
|   return repos;
 | |
| };
 |