aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--web/.eslintrc.json18
-rw-r--r--web/app/api/auth/[...nextauth]/route.tsx2
-rw-r--r--web/app/api/v1/links/route.ts105
-rw-r--r--web/app/globals.css38
-rw-r--r--web/app/layout.tsx1
-rw-r--r--web/components.json2
-rw-r--r--web/components/auth/logout.tsx11
-rw-r--r--web/lib/auth.ts10
-rw-r--r--web/lib/config.ts12
-rw-r--r--web/lib/prisma.ts2
-rw-r--r--web/lib/types/api/links.ts15
-rw-r--r--web/lib/types/next-auth.d.ts4
-rw-r--r--web/lib/utils.ts6
-rw-r--r--web/package.json20
-rw-r--r--web/tailwind.config.ts16
15 files changed, 134 insertions, 128 deletions
diff --git a/web/.eslintrc.json b/web/.eslintrc.json
index d971ae2a..c580ca7e 100644
--- a/web/.eslintrc.json
+++ b/web/.eslintrc.json
@@ -1,13 +1,4 @@
{
- "parser": "@typescript-eslint/parser",
- "parserOptions": {
- "project": "./tsconfig.json",
- "ecmaFeatures": {
- "jsx": true
- },
- "ecmaVersion": 12,
- "sourceType": "module"
- },
"extends": [
"next/core-web-vitals",
"eslint:recommended",
@@ -15,8 +6,11 @@
"plugin:react-hooks/recommended",
"plugin:@next/next/recommended",
"next",
- "plugin:@typescript-eslint/recommended",
- "plugin:@typescript-eslint/recommended-requiring-type-checking",
"prettier"
- ]
+ ],
+ "ignorePatterns": ["postcss.config.js"],
+ "rules": {
+ "no-redeclare": "off",
+ "@next/next/no-html-link-for-pages": "off"
+ }
}
diff --git a/web/app/api/auth/[...nextauth]/route.tsx b/web/app/api/auth/[...nextauth]/route.tsx
index bfcda516..e722926b 100644
--- a/web/app/api/auth/[...nextauth]/route.tsx
+++ b/web/app/api/auth/[...nextauth]/route.tsx
@@ -1,3 +1,3 @@
import { authHandler } from "@/lib/auth";
-export { authHandler as GET, authHandler as POST }
+export { authHandler as GET, authHandler as POST };
diff --git a/web/app/api/v1/links/route.ts b/web/app/api/v1/links/route.ts
index 5be1018e..97bfa3de 100644
--- a/web/app/api/v1/links/route.ts
+++ b/web/app/api/v1/links/route.ts
@@ -1,60 +1,67 @@
import { authOptions } from "@/lib/auth";
import prisma from "@/lib/prisma";
-import { ZNewBookmarkedLinkRequest, ZGetLinksResponse, ZBookmarkedLink } from "@/lib/types/api/links";
+import {
+ ZNewBookmarkedLinkRequest,
+ ZGetLinksResponse,
+ ZBookmarkedLink,
+} from "@/lib/types/api/links";
import { getServerSession } from "next-auth";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) {
- // TODO: We probably should be using an API key here instead of the session;
- const session = await getServerSession(authOptions);
- if (!session) {
- return new Response(null, { status: 401 });
- }
-
- const linkRequest = ZNewBookmarkedLinkRequest.safeParse(await request.json());
-
- if (!linkRequest.success) {
- return NextResponse.json({
- error: linkRequest.error.toString(),
- }, { status: 400 });
- }
-
- const link = await prisma.bookmarkedLink.create({
- data: {
- url: linkRequest.data.url,
- userId: session.user.id,
- }
- });
-
- let response: ZBookmarkedLink = { ...link };
-
- return NextResponse.json(response, { status: 201 });
+ // TODO: We probably should be using an API key here instead of the session;
+ const session = await getServerSession(authOptions);
+ if (!session) {
+ return new Response(null, { status: 401 });
+ }
+
+ const linkRequest = ZNewBookmarkedLinkRequest.safeParse(await request.json());
+
+ if (!linkRequest.success) {
+ return NextResponse.json(
+ {
+ error: linkRequest.error.toString(),
+ },
+ { status: 400 },
+ );
+ }
+
+ const link = await prisma.bookmarkedLink.create({
+ data: {
+ url: linkRequest.data.url,
+ userId: session.user.id,
+ },
+ });
+
+ let response: ZBookmarkedLink = { ...link };
+
+ return NextResponse.json(response, { status: 201 });
}
export async function GET() {
- // TODO: We probably should be using an API key here instead of the session;
- const session = await getServerSession(authOptions);
- if (!session) {
- return new Response(null, { status: 401 });
- }
- const links = await prisma.bookmarkedLink.findMany({
- where: {
- userId: session.user.id,
- },
+ // TODO: We probably should be using an API key here instead of the session;
+ const session = await getServerSession(authOptions);
+ if (!session) {
+ return new Response(null, { status: 401 });
+ }
+ const links = await prisma.bookmarkedLink.findMany({
+ where: {
+ userId: session.user.id,
+ },
+ select: {
+ id: true,
+ url: true,
+ createdAt: true,
+ details: {
select: {
- id: true,
- url: true,
- createdAt: true,
- details: {
- select: {
- title: true,
- description: true,
- imageUrl: true,
- }
- },
- }
- });
-
- let response: ZGetLinksResponse = { links };
- return NextResponse.json(response);
+ title: true,
+ description: true,
+ imageUrl: true,
+ },
+ },
+ },
+ });
+
+ let response: ZGetLinksResponse = { links };
+ return NextResponse.json(response);
}
diff --git a/web/app/globals.css b/web/app/globals.css
index 6a757250..8abdb15c 100644
--- a/web/app/globals.css
+++ b/web/app/globals.css
@@ -1,7 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
-
+
@layer base {
:root {
--background: 0 0% 100%;
@@ -9,63 +9,63 @@
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
-
+
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
-
+
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
-
+
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
-
+
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
-
+
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
-
+
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
-
+
--radius: 0.5rem;
}
-
+
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
-
+
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
-
+
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
-
+
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
-
+
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
-
+
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
-
+
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
-
+
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
-
+
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
}
-
+
@layer base {
* {
@apply border-border;
@@ -73,4 +73,4 @@
body {
@apply bg-background text-foreground;
}
-} \ No newline at end of file
+}
diff --git a/web/app/layout.tsx b/web/app/layout.tsx
index 3314e478..30d918df 100644
--- a/web/app/layout.tsx
+++ b/web/app/layout.tsx
@@ -1,6 +1,7 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
+import React from "react";
const inter = Inter({ subsets: ["latin"] });
diff --git a/web/components.json b/web/components.json
index 15f2b025..fa674c93 100644
--- a/web/components.json
+++ b/web/components.json
@@ -14,4 +14,4 @@
"components": "@/components",
"utils": "@/lib/utils"
}
-} \ No newline at end of file
+}
diff --git a/web/components/auth/logout.tsx b/web/components/auth/logout.tsx
index 87391c84..8d627f68 100644
--- a/web/components/auth/logout.tsx
+++ b/web/components/auth/logout.tsx
@@ -3,9 +3,14 @@ import { signOut } from "next-auth/react";
export const LogoutButton = () => {
return (
- <button className="btn btn-ghost normal-case" onClick={() => signOut({
- callbackUrl: "/",
- })}>
+ <button
+ className="btn btn-ghost normal-case"
+ onClick={() =>
+ signOut({
+ callbackUrl: "/",
+ })
+ }
+ >
Sign Out
</button>
);
diff --git a/web/lib/auth.ts b/web/lib/auth.ts
index 9b21e605..8b6527ec 100644
--- a/web/lib/auth.ts
+++ b/web/lib/auth.ts
@@ -1,5 +1,5 @@
-import NextAuth, { NextAuthOptions } from "next-auth"
-import { PrismaAdapter } from "@next-auth/prisma-adapter"
+import NextAuth, { NextAuthOptions } from "next-auth";
+import { PrismaAdapter } from "@next-auth/prisma-adapter";
import AuthentikProvider from "next-auth/providers/authentik";
import serverConfig from "@/lib/config";
import prisma from "@/lib/prisma";
@@ -15,11 +15,11 @@ export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(prisma),
providers: providers,
callbacks: {
- session({ session, token, user }) {
+ session({ session, user }) {
session.user = { ...user };
return session;
- }
- }
+ },
+ },
};
export const authHandler = NextAuth(authOptions);
diff --git a/web/lib/config.ts b/web/lib/config.ts
index ef86cb5a..1ebf8c3d 100644
--- a/web/lib/config.ts
+++ b/web/lib/config.ts
@@ -1,20 +1,20 @@
function buildAuthentikConfig() {
- let {id, secret, issuer} = process.env;
+ let { id, secret, issuer } = process.env;
if (!id || !secret || !issuer) {
return undefined;
}
return {
- clientId: id,
- clientSecret: secret,
- issuer: issuer,
- };
+ clientId: id,
+ clientSecret: secret,
+ issuer: issuer,
+ };
}
const serverConfig = {
auth: {
authentik: buildAuthentikConfig(),
- }
+ },
};
export default serverConfig;
diff --git a/web/lib/prisma.ts b/web/lib/prisma.ts
index d73ba5f2..b5bf6ce8 100644
--- a/web/lib/prisma.ts
+++ b/web/lib/prisma.ts
@@ -1,4 +1,4 @@
-import { PrismaClient } from '@prisma/client'
+import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
diff --git a/web/lib/types/api/links.ts b/web/lib/types/api/links.ts
index 81cde053..465fe133 100644
--- a/web/lib/types/api/links.ts
+++ b/web/lib/types/api/links.ts
@@ -5,20 +5,19 @@ export const ZBookmarkedLink = z.object({
url: z.string().url(),
createdAt: z.coerce.date(),
- details: z.object({
- title: z.string(),
- description: z.string(),
- imageUrl: z.string().url(),
- }).nullish(),
-
+ details: z
+ .object({
+ title: z.string(),
+ description: z.string(),
+ imageUrl: z.string().url(),
+ })
+ .nullish(),
});
export type ZBookmarkedLink = z.infer<typeof ZBookmarkedLink>;
-
// POST /v1/links
export const ZNewBookmarkedLinkRequest = ZBookmarkedLink.pick({ url: true });
-
// GET /v1/links
export const ZGetLinksResponse = z.object({
links: z.array(ZBookmarkedLink),
diff --git a/web/lib/types/next-auth.d.ts b/web/lib/types/next-auth.d.ts
index bdd3bd03..cd47dfce 100644
--- a/web/lib/types/next-auth.d.ts
+++ b/web/lib/types/next-auth.d.ts
@@ -1,10 +1,10 @@
-import NextAuth, { DefaultSession } from "next-auth"
+import { DefaultSession } from "next-auth";
declare module "next-auth" {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/
- interface Session {
+ export interface Session {
user: {
id: string;
} & DefaultSession["user"];
diff --git a/web/lib/utils.ts b/web/lib/utils.ts
index d084ccad..365058ce 100644
--- a/web/lib/utils.ts
+++ b/web/lib/utils.ts
@@ -1,6 +1,6 @@
-import { type ClassValue, clsx } from "clsx"
-import { twMerge } from "tailwind-merge"
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
+ return twMerge(clsx(inputs));
}
diff --git a/web/package.json b/web/package.json
index 2253d4e1..3ff0d2f8 100644
--- a/web/package.json
+++ b/web/package.json
@@ -10,11 +10,20 @@
},
"dependencies": {
"@next-auth/prisma-adapter": "^1.0.7",
+ "@next/eslint-plugin-next": "^14.1.0",
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
+ "@typescript-eslint/parser": "^6.21.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "install": "^0.13.0",
"lucide-react": "^0.322.0",
"next": "14.1.0",
"next-auth": "^4.24.5",
+ "prettier": "^3.2.5",
+ "prisma": "^5.9.1",
"react": "^18",
"react-dom": "^18",
"tailwind-merge": "^2.2.1",
@@ -30,15 +39,6 @@
"postcss": "^8",
"tailwindcss": "^3.3.0",
"eslint": "^8.56.0",
- "eslint-config-next": "14.1.0",
- "@next/eslint-plugin-next": "^14.1.0",
- "@typescript-eslint/eslint-plugin": "^6.21.0",
- "@typescript-eslint/parser": "^6.21.0",
- "eslint-config-prettier": "^9.1.0",
- "eslint-plugin-react": "^7.33.2",
- "eslint-plugin-react-hooks": "^4.6.0",
- "install": "^0.13.0",
- "prettier": "^3.2.5",
- "prisma": "^5.9.1"
+ "eslint-config-next": "14.1.0"
}
}
diff --git a/web/tailwind.config.ts b/web/tailwind.config.ts
index 84287e82..41668a3b 100644
--- a/web/tailwind.config.ts
+++ b/web/tailwind.config.ts
@@ -1,13 +1,13 @@
-import type { Config } from "tailwindcss"
+import type { Config } from "tailwindcss";
const config = {
darkMode: ["class"],
content: [
- './pages/**/*.{ts,tsx}',
- './components/**/*.{ts,tsx}',
- './app/**/*.{ts,tsx}',
- './src/**/*.{ts,tsx}',
- ],
+ "./pages/**/*.{ts,tsx}",
+ "./components/**/*.{ts,tsx}",
+ "./app/**/*.{ts,tsx}",
+ "./src/**/*.{ts,tsx}",
+ ],
prefix: "",
theme: {
container: {
@@ -75,6 +75,6 @@ const config = {
},
},
plugins: [require("tailwindcss-animate")],
-} satisfies Config
+} satisfies Config;
-export default config \ No newline at end of file
+export default config;