Skip to content

Commit

Permalink
feat: add used by
Browse files Browse the repository at this point in the history
  • Loading branch information
xhofe committed Oct 16, 2023
1 parent 0eb6ad2 commit 87ffe2c
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 12 deletions.
17 changes: 17 additions & 0 deletions app/(main)/used_by/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { title } from "@/components/primitives"
import { Show } from "./show"

export const metadata = {
title: "Used by",
}
export default function Page() {
return (
<section className="flex flex-col items-center justify-center gap-4 py-4">
<div className="inline-block max-w-lg text-center justify-center">
<h2 className={title({ color: "indigo", size: "sm" })}>Used&nbsp;</h2>
<h2 className={title({ size: "sm" })}>By</h2>
</div>
<Show />
</section>
)
}
49 changes: 49 additions & 0 deletions app/(main)/used_by/show.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"use client"
import { UsedRepoInfo } from "@/types"
import {
Card,
CardBody,
CardHeader,
Image,
Link,
Pagination,
} from "@nextui-org/react"
import { useSearchParams } from "next/navigation"
import { useEffect, useState } from "react"

export function Show() {
const searchParams = useSearchParams()
const [data, setData] = useState<UsedRepoInfo[]>([])
const [total, setTotal] = useState(0)
async function refetch() {
const resp = await fetch("/api/used_by?" + searchParams.toString())
const { data, total } = await resp.json()
setData(data)
setTotal(total)
}
useEffect(() => {
refetch()
}, [searchParams])
return (
<div className="w-full pt-4 md:px-10 lg:px-[14%] flex gap-2 flex-col">
<div className="grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(400px,1fr))]">
{data.map((repo) => (
<Card isPressable key={repo.name}>
<CardHeader className="pb-0">{repo.name}</CardHeader>
<CardBody className="p-3">
<Link href={`/api?repo=${repo.name}`}>
<Image src={`/api?repo=${repo.name}`} />
</Link>
</CardBody>
</Card>
))}
</div>
<div className="flex justify-center">
<Pagination
total={total}
page={parseInt(searchParams.get("page") ?? "1")}
/>
</div>
</div>
)
}
31 changes: 24 additions & 7 deletions app/api/github.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { LRUCache } from "lru-cache"
import { GhUser, GhUserUse } from "./types"
import { UsedRepoInfo } from "@/types"

const userCache = new LRUCache<string, GhUserUse[]>({
const repoCache = new LRUCache<string, GhUserUse[]>({
max: 500,
ttl: 1000 * 60 * 60 * 24,
})

const userNotFoundCache = new LRUCache<string, boolean>({
const repoNotFoundCache = new LRUCache<string, boolean>({
max: 100,
ttl: 1000 * 60 * 60 * 12,
})
Expand All @@ -16,16 +17,32 @@ const avatarCache = new LRUCache<string, string>({
ttl: 1000 * 60 * 60 * 24,
})

export function usedBy(per_page: number, page: number) {
let all = [] as UsedRepoInfo[]
repoCache.forEach((value, key) => {
all.push({
name: key,
count: value.length,
})
})
all = all.sort((a, b) => b.count - a.count)
const res = all.slice((page - 1) * per_page, page * per_page)
return {
data: res,
total: all.length,
}
}

export async function fetchRepo(repo: string, maxPages: number = 1) {
// validate repo
const repoRegex = /^[\w-]+\/[\w-]+$/
if (!repoRegex.test(repo)) {
throw new Error(`invalid repo: ${repo}`)
}
if (userCache.has(repo)) {
return userCache.get(repo)!
if (repoCache.has(repo)) {
return repoCache.get(repo)!
}
if (userNotFoundCache.has(repo)) {
if (repoNotFoundCache.has(repo)) {
throw new Error(`repo ${repo} not found`)
}
console.log(`fetching ${repo}`)
Expand All @@ -38,7 +55,7 @@ export async function fetchRepo(repo: string, maxPages: number = 1) {
const usersPage = await res.json()
if (usersPage.message) {
if (usersPage.message === "Not Found") {
userNotFoundCache.set(repo, true)
repoNotFoundCache.set(repo, true)
throw new Error(`repo ${repo} not found`)
}
throw new Error(`failed to fetch repo ${repo}: ${usersPage.message}`)
Expand All @@ -55,7 +72,7 @@ export async function fetchRepo(repo: string, maxPages: number = 1) {
avatar_url: user.avatar_url,
}
})
userCache.set(repo, usersUse)
repoCache.set(repo, usersUse)
return usersUse
}

Expand Down
1 change: 0 additions & 1 deletion app/api/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { NextRequest, NextResponse } from "next/server"
import { generateSVG } from "./svg"
import { calParams } from "@/utils/svg"

export async function GET(req: NextRequest): Promise<NextResponse> {
try {
Expand Down
14 changes: 14 additions & 0 deletions app/api/used_by/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { NextRequest, NextResponse } from "next/server"
import { usedBy } from "../github"

export async function GET(req: NextRequest) {
try {
const searchParams = req.nextUrl.searchParams
const per_page = parseInt(searchParams.get("per_page") || "20")
const page = parseInt(searchParams.get("page") || "1")
const users = usedBy(per_page, page)
return NextResponse.json(users)
} catch (e: any) {
return NextResponse.json({ error: e.message }, { status: 500 })
}
}
7 changes: 6 additions & 1 deletion components/footer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client"

import { Link } from "@nextui-org/react"
import { Divider, Link, link } from "@nextui-org/react"
import NextLink from "next/link"

export function Footer() {
return (
Expand All @@ -10,6 +11,10 @@ export function Footer() {
<Link isExternal href="https://nextjs.org/" className="text-primary">
NextJS
</Link>
<Divider orientation="vertical" className="h-5" />
<NextLink className={link()} href="/used_by">
Used by
</NextLink>
</div>
</footer>
)
Expand Down
11 changes: 8 additions & 3 deletions types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import {SVGProps} from "react";
import { SVGProps } from "react"

export type IconSvgProps = SVGProps<SVGSVGElement> & {
size?: number;
};
size?: number
}

export type UsedRepoInfo = {
name: string
count: number
}

0 comments on commit 87ffe2c

Please sign in to comment.