diff --git a/.gitignore b/.gitignore index 30bc162..1a61733 100755 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/node_modules \ No newline at end of file +/node_modules +test/ \ No newline at end of file diff --git a/core/actions/gh/repos.ts b/core/actions/gh/repos.ts new file mode 100644 index 0000000..bceba86 --- /dev/null +++ b/core/actions/gh/repos.ts @@ -0,0 +1,37 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use server"; + +import axios from "axios"; +import { getAccessToken } from "@/db/user"; +import { formatTimeAgo } from "@/lib/time"; +import { Repo } from "@/types/gh"; + +export async function getRepos(github_id: number) { + if (!github_id || github_id == -1) return []; + const access_token = await getAccessToken(github_id); + if (!access_token) return []; + + try { + const res = await axios.get( + `https://api.github.com/user/repos?visibility=all&sort=updated`, + { + headers: { + Authorization: `token ${access_token}`, + Accept: "application/vnd.github.v3+json", + }, + }, + ); + + return (res.data as Repo[]) + .map((i: any) => ({ + name: i.name, + last_updated: formatTimeAgo(new Date(i.updated_at)), + private: i.private, + owner: i.owner.login.toLowerCase(), + })) + .slice(0, 10); + } catch (error) { + console.log(error); + return []; + } +} diff --git a/core/app/api/gh/repo/route.ts b/core/app/api/gh/repo/route.ts new file mode 100644 index 0000000..47f8681 --- /dev/null +++ b/core/app/api/gh/repo/route.ts @@ -0,0 +1,12 @@ +import type { NextApiRequest, NextApiResponse } from "next"; + +type ResponseData = { + message: string; +}; + +export default function handler( + req: NextApiRequest, + res: NextApiResponse, +) { + res.status(200).json({ message: "Hello from Next.js!" }); +} diff --git a/core/app/dashboard/page.tsx b/core/app/dashboard/page.tsx index 8c10343..5e80b72 100644 --- a/core/app/dashboard/page.tsx +++ b/core/app/dashboard/page.tsx @@ -1,6 +1,30 @@ -import ProtectRoute from "@/components/ProtectRoute"; -import React from "react"; +"use client"; -export default async function Dashboard() { - return (await ProtectRoute()) ??
page
; +import { useEffect, useState } from "react"; +import { useSession } from "next-auth/react"; +import { getRepos } from "@/actions/gh/repos"; +import { Repo } from "@/types/gh"; +import ProtectClientRoute from "@/components/ProtectRoute/ProtectClientRoute"; +import Onboarding from "@/components/Dash/OnBoarding"; + +export default function DashBoard() { + const { data: session } = useSession(); + const protectRoute = ProtectClientRoute(); + const [repos, setRepos] = useState([]); + const [loading, setLoading] = useState(false); + + useEffect(() => { + (async () => { + setLoading(true); + setRepos( + await getRepos(session?.user.github_id ?? -1).finally(() => { + setLoading(false); + }), + ); + })(); + }, [session?.user.github_id]); + + if (protectRoute) return protectRoute; + + return ; } diff --git a/core/components/Dash/OnBoarding.tsx b/core/components/Dash/OnBoarding.tsx new file mode 100644 index 0000000..6df2251 --- /dev/null +++ b/core/components/Dash/OnBoarding.tsx @@ -0,0 +1,130 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { LockIcon, SearchIcon } from "lucide-react"; +import Image from "next/image"; +import { Repo } from "@/types/gh"; +import Link from "next/link"; +import { Skeleton } from "@/components/ui/skeleton"; + +export default function Onboarding({ + repos, + loading, +}: { + repos: Repo[]; + loading: boolean; +}) { + return ( +
+
+

+ Let's build something new. +

+

+ To deploy a new Project, select the repository you want to deploy. The + repository must be hosted on GitHub. +

+
+ + + Import Git Repository + + +
+ +
+ + +
+
+
+ {loading + ? Array.from({ length: 3 }).map((_, index) => ( +
+
+ +
+ + +
+
+ +
+ )) + : repos.map((repo, index) => ( +
+
+
+ {repo.name[0]} +
+
+
+ + {repo.name} + + {repo.private && ( + + )} +
+

+ {repo.last_updated} +

+
+
+ +
+ ))} +
+ +
+
+
+ Onboarding +
+
+
+
+ ); +} diff --git a/core/components/ProtectRoute.tsx b/core/components/ProtectRoute.tsx deleted file mode 100644 index 5425591..0000000 --- a/core/components/ProtectRoute.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { getServerSession } from "next-auth"; -import React from "react"; - -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "@/components/ui/card"; -import LoginWithGithub from "./LoginWithGithub"; -import { authOptions } from "@/lib/options"; - -export default async function ProtectRoute() { - const session = await getServerSession(authOptions); - console.log("session", session); - - if (!session) { - return ( -
- - - Unauthorized Access - - You are not authorized to view this page. - - - - - - -
- ); - } -} diff --git a/core/components/LoginWithGithub.tsx b/core/components/ProtectRoute/LoginWithGithub.tsx similarity index 89% rename from core/components/LoginWithGithub.tsx rename to core/components/ProtectRoute/LoginWithGithub.tsx index c80fe5a..9117f25 100644 --- a/core/components/LoginWithGithub.tsx +++ b/core/components/ProtectRoute/LoginWithGithub.tsx @@ -1,7 +1,7 @@ "use client"; import { signIn } from "next-auth/react"; -import { Button } from "./ui/button"; +import { Button } from "@/components/ui/button"; import { GithubIcon } from "lucide-react"; export default function LoginWithGithub() { diff --git a/core/components/ProtectRoute/ProtectClientRoute.tsx b/core/components/ProtectRoute/ProtectClientRoute.tsx new file mode 100644 index 0000000..27670e8 --- /dev/null +++ b/core/components/ProtectRoute/ProtectClientRoute.tsx @@ -0,0 +1,9 @@ +import { useSession } from "next-auth/react"; +import ProtectRouteUI from "../ProtectRoute"; + +export default function ProtectClientRoute() { + const { data: session } = useSession(); + if (!session) { + return ; + } +} diff --git a/core/components/ProtectRoute/ProtectServerRoute.tsx b/core/components/ProtectRoute/ProtectServerRoute.tsx new file mode 100644 index 0000000..4ce2ea7 --- /dev/null +++ b/core/components/ProtectRoute/ProtectServerRoute.tsx @@ -0,0 +1,10 @@ +import { getServerSession } from "next-auth"; +import { authOptions } from "@/lib/options"; +import ProtectRouteUI from "../ProtectRoute"; + +export async function ProtectServerRoute() { + const session = await getServerSession(authOptions); + if (!session) { + return ; + } +} diff --git a/core/components/ProtectRoute/index.tsx b/core/components/ProtectRoute/index.tsx new file mode 100644 index 0000000..c15a943 --- /dev/null +++ b/core/components/ProtectRoute/index.tsx @@ -0,0 +1,26 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import LoginWithGithub from "./LoginWithGithub"; + +export default function ProtectRouteUI() { + return ( +
+ + + Unauthorized Access + + You are not authorized to view this page. + + + + + + +
+ ); +} diff --git a/core/components/ui/badge.tsx b/core/components/ui/badge.tsx new file mode 100644 index 0000000..f795980 --- /dev/null +++ b/core/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@/lib/utils"; + +const badgeVariants = cva( + "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ); +} + +export { Badge, badgeVariants }; diff --git a/core/components/ui/input.tsx b/core/components/ui/input.tsx new file mode 100644 index 0000000..ef29a4a --- /dev/null +++ b/core/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ); + }, +); +Input.displayName = "Input"; + +export { Input }; diff --git a/core/components/ui/select.tsx b/core/components/ui/select.tsx new file mode 100644 index 0000000..11fc181 --- /dev/null +++ b/core/components/ui/select.tsx @@ -0,0 +1,164 @@ +"use client"; + +import * as React from "react"; +import { + CaretSortIcon, + CheckIcon, + ChevronDownIcon, + ChevronUpIcon, +} from "@radix-ui/react-icons"; +import * as SelectPrimitive from "@radix-ui/react-select"; + +import { cn } from "@/lib/utils"; + +const Select = SelectPrimitive.Root; + +const SelectGroup = SelectPrimitive.Group; + +const SelectValue = SelectPrimitive.Value; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className, + )} + {...props} + > + {children} + + + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +}; diff --git a/core/components/ui/skeleton.tsx b/core/components/ui/skeleton.tsx new file mode 100644 index 0000000..c26c4ea --- /dev/null +++ b/core/components/ui/skeleton.tsx @@ -0,0 +1,15 @@ +import { cn } from "@/lib/utils"; + +function Skeleton({ + className, + ...props +}: React.HTMLAttributes) { + return ( +
+ ); +} + +export { Skeleton }; diff --git a/core/lib/db.ts b/core/db/index.ts similarity index 100% rename from core/lib/db.ts rename to core/db/index.ts diff --git a/core/db/user.ts b/core/db/user.ts new file mode 100644 index 0000000..cc94dc2 --- /dev/null +++ b/core/db/user.ts @@ -0,0 +1,6 @@ +import { prisma } from "../db"; + +export async function getAccessToken(github_id: number) { + const user = await prisma.user.findUnique({ where: { github_id } }); + return user?.access_token; +} diff --git a/core/lib/options.ts b/core/lib/options.ts index ddf9ab0..8cd4c20 100644 --- a/core/lib/options.ts +++ b/core/lib/options.ts @@ -1,4 +1,4 @@ -import { prisma } from "@/lib/db"; +import { prisma } from "@/db"; import { NextAuthOptions } from "next-auth"; import GithubProvider from "next-auth/providers/github"; @@ -19,89 +19,88 @@ export const authOptions: NextAuthOptions = { ], callbacks: { async signIn({ user, account, profile }) { + if (!profile || !account) return false; + + const github_id = profile.id ? parseInt(profile.id) : 0; + if (!github_id) return false; + const db_data = { - name: profile?.name, - email: user?.email, - avatar_url: profile?.avatar_url, - bio: profile?.bio, - id: parseInt(profile?.id ?? ""), - access_token: account?.access_token, + github_id, + name: profile.name ?? user.name ?? profile.login ?? "", + email: user.email ?? "", + avatar_url: profile.avatar_url, + bio: profile.bio, + access_token: account.access_token ?? "", + username: profile.login ?? "", }; - if (!db_data.name) { - db_data.name = db_data.email?.split("@")[0]; + if ( + !db_data.name || + !db_data.email || + !db_data.access_token || + !db_data.username + ) { + return false; } - const nonNullableFiels: (keyof typeof db_data)[] = [ - "name", - "email", - "avatar_url", - "id", - "access_token", - ]; - for (const field of nonNullableFiels) { - if (!db_data[field]) { - return false; - } - } - try { - // await prisma.user.create({ - // data: { - // access_token: db_data.access_token!, - // avatar: db_data.avatar_url!, - // bio: db_data.bio!, - // email: db_data.email!, - // github_id: db_data.id!, - // name: db_data.name!, - // }, - // }); + const upsertedUser = await prisma.user.upsert({ + where: { github_id: db_data.github_id }, + create: { + github_id: db_data.github_id, + access_token: db_data.access_token, + avatar: db_data.avatar_url ?? "", + bio: db_data.bio ?? "", + email: db_data.email, + name: db_data.name, + github_username: db_data.username, + }, + update: { + access_token: db_data.access_token, + avatar: db_data.avatar_url, + bio: db_data.bio, + email: db_data.email, + name: db_data.name, + github_username: db_data.username, + }, + }); - const res = await prisma.user.upsert({ - where: { - github_id: db_data.id!, - }, - create: { - access_token: db_data.access_token!, - avatar: db_data.avatar_url!, - bio: db_data.bio!, - email: db_data.email!, - github_id: db_data.id!, - name: db_data.name!, - }, - update: { - access_token: db_data.access_token!, - avatar: db_data.avatar_url!, - bio: db_data.bio!, - email: db_data.email!, - github_id: db_data.id!, - name: db_data.name!, - }, - }); - console.log(res); - } catch (error) { - console.log(error); - } + // Assign the database-generated ID and GitHub ID to the user object + user.id = upsertedUser.id; // Database ID (string) + user.github_id = upsertedUser.github_id; // GitHub ID (number) return true; }, - async session({ session, token }) { - if (session.user) { - session.user.bio = token.bio as string | undefined; - session.user.avatar_url = token.avatar_url as string | undefined; - } - return session; - }, - async jwt({ token, user, profile }) { if (user) { - token.id = user.id; - token.bio = profile?.bio as string | undefined; - token.avatar_url = profile?.avatar_url as string | undefined; + token.id = user.id; // Database ID (string) + token.github_id = user.github_id; // GitHub ID (number) token.name = user.name; + token.email = user.email; + token.username = (profile?.login as string) ?? ""; + } + if (profile) { + token.bio = profile.bio as string | undefined; + token.avatar_url = profile.avatar_url as string | undefined; } return token; }, + + async session({ session, token }) { + return { + ...session, + user: { + ...session.user, + id: token.id, // Database ID (string) + github_id: token.github_id, // GitHub ID (number) + name: token.name, + email: token.email, + bio: token.bio, + avatar_url: token.avatar_url, + username: token.username, + }, + }; + }, }, session: { diff --git a/core/lib/time.ts b/core/lib/time.ts new file mode 100644 index 0000000..4e64d2b --- /dev/null +++ b/core/lib/time.ts @@ -0,0 +1,15 @@ +export function formatTimeAgo(date: Date) { + const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(seconds / 3600); + const days = Math.floor(seconds / 86400); + const weeks = Math.floor(days / 7); + const months = Math.floor(days / 30); + + if (months > 0) return `${months} month${months > 1 ? "s" : ""} ago`; + if (weeks > 0) return `${weeks} week${weeks > 1 ? "s" : ""} ago`; + if (days > 0) return `${days} day${days > 1 ? "s" : ""} ago`; + if (hours > 0) return `${hours} hour${hours > 1 ? "s" : ""} ago`; + if (minutes > 0) return `${minutes} min${minutes > 1 ? "s" : ""} ago`; + return `${seconds}s ago`; +} diff --git a/core/next.config.mjs b/core/next.config.mjs index 1387379..2423688 100644 --- a/core/next.config.mjs +++ b/core/next.config.mjs @@ -8,6 +8,12 @@ const nextConfig = { port: "", pathname: "/u/**", }, + { + protocol: "https", + hostname: "https://storage.googleapis.com", + port: "", + pathname: "/**", + }, ], }, }; diff --git a/core/package-lock.json b/core/package-lock.json index d995b4e..0513420 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -13,7 +13,9 @@ "@prisma/client": "^5.20.0", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.0", + "axios": "^1.7.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.447.0", @@ -1222,6 +1224,12 @@ "@prisma/debug": "5.20.0" } }, + "node_modules/@radix-ui/number": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", + "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==", + "license": "MIT" + }, "node_modules/@radix-ui/primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", @@ -1664,6 +1672,49 @@ } } }, + "node_modules/@radix-ui/react-select": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.2.tgz", + "integrity": "sha512-rZJtWmorC7dFRi0owDmoijm6nSJH1tVw64QGiNIZ9PNLyBDtG+iAq+XGsya052At4BfarzY/Dhv9wrrUr6IMZA==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", @@ -1748,6 +1799,21 @@ } } }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", + "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-rect": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", @@ -1784,6 +1850,29 @@ } } }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", + "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/rect": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", @@ -2396,6 +2485,12 @@ "dev": true, "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -2422,6 +2517,17 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -2705,6 +2811,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -3032,6 +3150,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -3911,6 +4038,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3937,6 +4084,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5220,6 +5381,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6138,6 +6320,12 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/core/package.json b/core/package.json index 1cb2b91..d6b0e03 100644 --- a/core/package.json +++ b/core/package.json @@ -19,7 +19,9 @@ "@prisma/client": "^5.20.0", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.0", + "axios": "^1.7.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.447.0", @@ -41,9 +43,9 @@ "eslint": "^8", "eslint-config-next": "14.2.14", "postcss": "^8", + "prettier-plugin-tailwindcss": "^0.6.6", "prisma": "^5.20.0", "tailwindcss": "^3.4.1", - "typescript": "^5", - "prettier-plugin-tailwindcss": "^0.6.6" + "typescript": "^5" } -} \ No newline at end of file +} diff --git a/core/prisma/migrations/20241007105726_user_schema_init/migration.sql b/core/prisma/migrations/20241007125025_user_schema_init/migration.sql similarity index 95% rename from core/prisma/migrations/20241007105726_user_schema_init/migration.sql rename to core/prisma/migrations/20241007125025_user_schema_init/migration.sql index f02cec5..d39fa89 100644 --- a/core/prisma/migrations/20241007105726_user_schema_init/migration.sql +++ b/core/prisma/migrations/20241007125025_user_schema_init/migration.sql @@ -3,6 +3,7 @@ CREATE TABLE "User" ( "id" TEXT NOT NULL, "github_id" INTEGER NOT NULL, "name" TEXT DEFAULT '', + "github_username" TEXT NOT NULL, "email" TEXT NOT NULL, "bio" TEXT, "avatar" TEXT NOT NULL, diff --git a/core/prisma/schema.prisma b/core/prisma/schema.prisma index bebdd26..2435233 100644 --- a/core/prisma/schema.prisma +++ b/core/prisma/schema.prisma @@ -8,13 +8,14 @@ datasource db { } model User { - id String @id @default(cuid()) - github_id Int @unique - name String? @default("") - email String @unique - bio String? - avatar String - access_token String + id String @id @default(cuid()) + github_id Int @unique + name String? @default("") + github_username String + email String @unique + bio String? + avatar String + access_token String } model Session { diff --git a/core/types/gh.ts b/core/types/gh.ts new file mode 100644 index 0000000..7fdfc54 --- /dev/null +++ b/core/types/gh.ts @@ -0,0 +1,6 @@ +export type Repo = { + name: string; + last_updated: string; + private: boolean; + owner: string; +}; diff --git a/core/types/nat-auth.d.ts b/core/types/nat-auth.d.ts deleted file mode 100644 index 47c0b43..0000000 --- a/core/types/nat-auth.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import "next-auth"; - -declare module "next-auth" { - interface User { - id: string; - } - - interface Profile { - bio: string; - avatar_url: string; - id: string; - } - - interface Session { - user: User & { - bio?: string; - avatar_url?: string; - }; - } -} diff --git a/core/types/next-auth.d.ts b/core/types/next-auth.d.ts new file mode 100644 index 0000000..06e2030 --- /dev/null +++ b/core/types/next-auth.d.ts @@ -0,0 +1,47 @@ +import "next-auth"; +import { DefaultSession } from "next-auth"; + +declare module "next-auth" { + interface Session { + user: { + id: string; + github_id: number; + name: string; + email: string; + bio?: string; + avatar_url?: string; + username: string; + } & DefaultSession["user"]; + } + + interface User { + id: string; + github_id: number; + name: string; + email: string; + bio?: string; + avatar_url?: string; + username: string; + } + + interface Profile { + id?: string; + name?: string; + email?: string; + avatar_url?: string; + bio?: string; + login?: string; + } +} + +declare module "next-auth/jwt" { + interface JWT { + id: string; + github_id: number; + name: string; + email: string; + bio?: string; + avatar_url?: string; + username: string; + } +} diff --git a/docker-builder/src/helper/build.ts b/docker-builder/src/helper/build.ts index 8fb3876..5f4236d 100755 --- a/docker-builder/src/helper/build.ts +++ b/docker-builder/src/helper/build.ts @@ -27,42 +27,42 @@ export const buildAndCLone = async () => { }, ); - await executeProcess( - async function () { - await runCommand({ - command: "npm install", - cwd: workDir, - }); - }, - { - initialLog: "Installing dependencies", - finalLog: `Successfully installed dependencies`, - }, - ); + // await executeProcess( + // async function () { + // await runCommand({ + // command: "npm install", + // cwd: workDir, + // }); + // }, + // { + // initialLog: "Installing dependencies", + // finalLog: `Successfully installed dependencies`, + // }, + // ); - console.log("Building the project", BUILD_COMMAND); + // console.log("Building the project", BUILD_COMMAND); - await executeProcess( - async function () { - await runCommand({ - command: BUILD_COMMAND, - cwd: workDir, - }); - }, - { - initialLog: "Building the project", - finalLog: `Successfully cloned, installed dependencies, and built the project`, - }, - ); + // await executeProcess( + // async function () { + // await runCommand({ + // command: BUILD_COMMAND, + // cwd: workDir, + // }); + // }, + // { + // initialLog: "Building the project", + // finalLog: `Successfully cloned, installed dependencies, and built the project`, + // }, + // ); - console.log(`${workDir}/${BUILD_FOLDER}/* ${buildDir}`); + // console.log(`${workDir}/${BUILD_FOLDER}/* ${buildDir}`); - await executeProcess(async function () { - await runCommand({ - command: `mv '${workDir}/${BUILD_FOLDER}/'* '${buildDir}'`, - cwd: workDir, - }); - }, {}); + // await executeProcess(async function () { + // await runCommand({ + // command: `mv '${workDir}/${BUILD_FOLDER}/'* '${buildDir}'`, + // cwd: workDir, + // }); + // }, {}); } catch (err: Error | any) { console.error(`Failed to complete the process: ${err.message}`); process.exit(1); diff --git a/package-lock.json b/package-lock.json index 9413b41..df33628 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,10 +4,245 @@ "requires": true, "packages": { "": { + "dependencies": { + "@octokit/rest": "^21.0.2", + "axios": "^1.7.7" + }, "devDependencies": { "husky": "^8.0.0" } }, + "node_modules/@octokit/auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz", + "integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz", + "integrity": "sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.0.0", + "@octokit/request": "^9.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", + "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz", + "integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.5.tgz", + "integrity": "sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.2.6", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.6.tgz", + "integrity": "sha512-wMsdyHMjSfKjGINkdGKki06VEkgdEldIGstIEyGX0wbYHGByOwN/KiM+hAAlUwAtPkP3gvXtVQA9L3ITdV2tVw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.6.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/request": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", + "integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz", + "integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.2.tgz", + "integrity": "sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ==", + "license": "MIT", + "dependencies": { + "@octokit/core": "^6.1.2", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.6.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.1.tgz", + "integrity": "sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "license": "Apache-2.0" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/husky": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", @@ -23,6 +258,39 @@ "funding": { "url": "https://github.com/sponsors/typicode" } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "license": "ISC" } } } diff --git a/package.json b/package.json index 695c3b5..aee3b51 100644 --- a/package.json +++ b/package.json @@ -4,5 +4,9 @@ }, "scripts": { "prepare": "husky install" + }, + "dependencies": { + "@octokit/rest": "^21.0.2", + "axios": "^1.7.7" } -} \ No newline at end of file +}