From ffceba01abc2cf094a55999353636645b9d2c135 Mon Sep 17 00:00:00 2001 From: Luana Nunes Date: Wed, 18 Oct 2023 18:42:10 -0300 Subject: [PATCH 01/30] feat: create endpoint to get users --- src/app/api/users/route.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/app/api/users/route.ts diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts new file mode 100644 index 0000000..07ed233 --- /dev/null +++ b/src/app/api/users/route.ts @@ -0,0 +1,20 @@ +import { user } from "@/dao/user.dao"; +import { NextApiRequest, NextApiResponse } from "next"; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method === "GET") { + try { + await user; + + res.status(200).json(user); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal Server Error" }); + } + } else { + res.status(405).json({ error: "Method not allowed" }); + } +} From a918fb29da131b06fecbcc5f67228dc2989cf824 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:59:21 -0300 Subject: [PATCH 02/30] Update route.ts --- src/app/api/users/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 07ed233..d498018 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -12,7 +12,7 @@ export default async function handler( res.status(200).json(user); } catch (error) { console.error(error); - res.status(500).json({ error: "Internal Server Error" }); + res.status(500).json({ error: "Internal Server Error. Please try again" }); } } else { res.status(405).json({ error: "Method not allowed" }); From 4e3ec12b25e358f474640af6b56fccc38950aa90 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:27:26 -0300 Subject: [PATCH 03/30] Create user.dao.ts --- src/app/api/users/user.dao.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/api/users/user.dao.ts diff --git a/src/app/api/users/user.dao.ts b/src/app/api/users/user.dao.ts new file mode 100644 index 0000000..7fc0d6b --- /dev/null +++ b/src/app/api/users/user.dao.ts @@ -0,0 +1,11 @@ +const users = [ { id: 1, name: "User 1" }, + { id: 2, name: "User 2" },]; + +export async function getUserById(id: number) { + const user = users.find((u) => u.id === id); + return user; +} + +export async function getAllUsers() { + return users; +} From d17189997ad62108f2f6e9a781c5526fc440e793 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 25 Oct 2023 16:28:03 -0300 Subject: [PATCH 04/30] Update route.ts --- src/app/api/users/route.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index d498018..5211fc3 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,4 +1,4 @@ -import { user } from "@/dao/user.dao"; +import { getAllUsers } from "@/dao/user.dao"; import { NextApiRequest, NextApiResponse } from "next"; export default async function handler( @@ -7,9 +7,8 @@ export default async function handler( ) { if (req.method === "GET") { try { - await user; - - res.status(200).json(user); + const users = await getAllUsers(); + res.status(200).json(users); } catch (error) { console.error(error); res.status(500).json({ error: "Internal Server Error. Please try again" }); From 743c01e324e545e292d248ab64ac9b5d993e0d9a Mon Sep 17 00:00:00 2001 From: Luana Nunes Date: Wed, 25 Oct 2023 17:05:39 -0300 Subject: [PATCH 05/30] ref: add initial fixes --- src/app/api/users/route.ts | 40 +++++++++++++++++++++++--------------- src/dao/user.dao.ts | 4 ++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index d498018..b154037 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,20 +1,28 @@ import { user } from "@/dao/user.dao"; -import { NextApiRequest, NextApiResponse } from "next"; +import { NextResponse } from "next/server"; -export default async function handler( - req: NextApiRequest, - res: NextApiResponse -) { - if (req.method === "GET") { - try { - await user; +// export default async function handler( +// req: NextRequest, +// res: NextResponse +// ) { +// if (req.method === "GET") { +// try { +// await user; - res.status(200).json(user); - } catch (error) { - console.error(error); - res.status(500).json({ error: "Internal Server Error. Please try again" }); - } - } else { - res.status(405).json({ error: "Method not allowed" }); - } +// res.status(200).json(user); +// } catch (error) { +// console.error(error); +// res +// .status(500) +// .json({ error: "Internal Server Error. Please try again" }); +// }podcodar +// } else { +// res.status(405).json({ error: "Method not allowed" }); +// } +// } + +export async function GET() { + // fetch all user data from database + const users = await user.fetchUsers(); + return NextResponse.json({ users }); } diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index 7aa7ed2..8ed6ce8 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -28,6 +28,10 @@ class UserDAO { }); } + async fetchUsers() { + return await prisma.user.findMany(); + } + async isOboardingFinished(username: string) { const user = (await this.fetchUserBy({ username })) ?? From 0c972e797567aa4076b03d6d5531b1ccc3e6d411 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:29:40 -0300 Subject: [PATCH 06/30] Delete src/app/api/users/user.dao.ts --- src/app/api/users/user.dao.ts | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/app/api/users/user.dao.ts diff --git a/src/app/api/users/user.dao.ts b/src/app/api/users/user.dao.ts deleted file mode 100644 index 6af2fcd..0000000 --- a/src/app/api/users/user.dao.ts +++ /dev/null @@ -1,10 +0,0 @@ -const users = [{ id: 1, name: "User 1" }, { id: 2, name: "User 2" },]; - -export async function getUserById(id: number) { - const user = users.find((u) => u.id === id); - return user; -} - -export async function getAllUsers() { - return users; -} From ff74415c31f17457cb95a65ae71b4bfbace07f8c Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:30:58 -0300 Subject: [PATCH 07/30] Update route.ts --- src/app/api/users/route.ts | 70 ++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 7667b6f..4dc3788 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,46 +1,34 @@ import { user } from "@/dao/user.dao"; -import { NextResponse } from "next/server"; +import { NextApiRequest, NextApiResponse } from 'next'; -// export default async function handler( -// req: NextRequest, -// res: NextResponse -// ) { -// if (req.method === "GET") { -// try { -// await user; +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method === 'GET') { + try { + const users = await user.fetchUsers(); + res.status(200).json(users); + } catch (error) { + console.error('Error fetching users:', error); + res.status(500).json({ error: 'Internal Server Error' }); + } + } else if (req.method === 'POST') { + try { + const { loginUser } = req.body; -// res.status(200).json(user); -// } catch (error) { -// console.error(error); -// res -// .status(500) -// .json({ error: "Internal Server Error. Please try again" }); -// }podcodar -// } else { -// res.status(405).json({ error: "Method not allowed" }); -// } -// } + if (!loginUser) { + return res.status(400).json({ error: 'Missing loginUser data' }); + } -export async function GET() { - // fetch all user data from database - const users = await user.fetchUsers(); - return NextResponse.json({ users }); -} + const createdUser = await user.createUser(loginUser); -// Modificações commit Ogata -// export default async function handler( -// req: NextApiRequest, -// res: NextApiResponse -// ) { -// if (req.method === "GET") { -// try { -// const users = await getAllUsers(); -// res.status(200).json(users); -// } catch (error) { -// console.error(error); -// res.status(500).json({ error: "Internal Server Error. Please try again" }); -// } -// } else { -// res.status(405).json({ error: "Method not allowed" }); -// } -// } + res.status(201).json(createdUser); + } catch (error) { + console.error('Error creating user:', error); + res.status(500).json({ error: 'Internal Server Error' }); + } + } else { + res.status(405).json({ error: 'Method Not Allowed' }); + } +} From 40f1355c2d0d64b8419aaf763ef4484532cd0c2e Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:35:58 -0300 Subject: [PATCH 08/30] Update user.dao.ts --- src/dao/user.dao.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index 8ed6ce8..fa22fc2 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -32,6 +32,23 @@ class UserDAO { return await prisma.user.findMany(); } + async fetchUsers( + filter: { username?: string; email?: string }, + page: number = 1, + pageSize: number = 10 + ) { + const skip = (page - 1) * pageSize; + + return await prisma.user.findMany({ + where: { + username: filter.username ? { contains: filter.username } : undefined, + email: filter.email ? { contains: filter.email } : undefined, + }, + skip, + take: pageSize, + }); + } + async isOboardingFinished(username: string) { const user = (await this.fetchUserBy({ username })) ?? From 2e8779ca5064dfc9d5a0f95ad2178cd0cde4a6d6 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:36:38 -0300 Subject: [PATCH 09/30] Update route.ts --- src/app/api/users/route.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 4dc3788..ae3ecef 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -7,7 +7,14 @@ export default async function handler( ) { if (req.method === 'GET') { try { - const users = await user.fetchUsers(); + const { username, email, page, pageSize } = req.query; + + const filter = { + username: username as string | undefined, + email: email as string | undefined, + }; + + const users = await user.fetchUsers(filter, parseInt(page as string) || 1, parseInt(pageSize as string) || 10); res.status(200).json(users); } catch (error) { console.error('Error fetching users:', error); @@ -15,7 +22,7 @@ export default async function handler( } } else if (req.method === 'POST') { try { - const { loginUser } = req.body; + const { loginUser } = req.body; if (!loginUser) { return res.status(400).json({ error: 'Missing loginUser data' }); From 9c53c554bcb509ff2475d0f83729f8411f49f261 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:40:47 -0300 Subject: [PATCH 10/30] fix: route.ts --- src/app/api/users/route.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index ae3ecef..fa32ad9 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -32,7 +32,6 @@ export default async function handler( res.status(201).json(createdUser); } catch (error) { - console.error('Error creating user:', error); res.status(500).json({ error: 'Internal Server Error' }); } } else { From 687e11a2afd7daab7b668e11e14f827d55a7453b Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:55:23 -0300 Subject: [PATCH 11/30] Update route.ts with prisma --- src/app/api/users/route.ts | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index fa32ad9..0f36fdd 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,4 +1,4 @@ -import { user } from "@/dao/user.dao"; +import prisma from "@/prisma/client"; import { NextApiRequest, NextApiResponse } from 'next'; export default async function handler( @@ -14,10 +14,17 @@ export default async function handler( email: email as string | undefined, }; - const users = await user.fetchUsers(filter, parseInt(page as string) || 1, parseInt(pageSize as string) || 10); + const users = await prisma.user.findMany({ + where: { + username: filter.username ? { contains: filter.username } : undefined, + email: filter.email ? { contains: filter.email } : undefined, + }, + skip: (parseInt(page as string) || 1 - 1) * (parseInt(pageSize as string) || 10), + take: parseInt(pageSize as string) || 10, + }); + res.status(200).json(users); } catch (error) { - console.error('Error fetching users:', error); res.status(500).json({ error: 'Internal Server Error' }); } } else if (req.method === 'POST') { @@ -28,10 +35,18 @@ export default async function handler( return res.status(400).json({ error: 'Missing loginUser data' }); } - const createdUser = await user.createUser(loginUser); + const createdUser = await prisma.user.create({ + data: { + username: loginUser.email ?? "", + email: loginUser.email ?? "", + name: loginUser.name ?? "", + avatar: loginUser.image ?? undefined, + }, + }); res.status(201).json(createdUser); } catch (error) { + console.error('Error creating user:', error); res.status(500).json({ error: 'Internal Server Error' }); } } else { From 978f039367cc11552e5d423dba171abb210aa0a7 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 18:18:56 -0300 Subject: [PATCH 12/30] fix: user.dao.ts duplication --- src/dao/user.dao.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index fa22fc2..963d251 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -28,11 +28,7 @@ class UserDAO { }); } - async fetchUsers() { - return await prisma.user.findMany(); - } - - async fetchUsers( + async fetchUsers( filter: { username?: string; email?: string }, page: number = 1, pageSize: number = 10 From 773dd48b9fcdfaae7e20624f7439c8e3e06dbf19 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 19:38:45 -0300 Subject: [PATCH 13/30] change the place on route.ts --- src/app/api/users/route.ts | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 0f36fdd..b385677 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,4 +1,4 @@ -import prisma from "@/prisma/client"; +import { user } from "@/dao/user.dao"; import { NextApiRequest, NextApiResponse } from 'next'; export default async function handler( @@ -14,41 +14,11 @@ export default async function handler( email: email as string | undefined, }; - const users = await prisma.user.findMany({ - where: { - username: filter.username ? { contains: filter.username } : undefined, - email: filter.email ? { contains: filter.email } : undefined, - }, - skip: (parseInt(page as string) || 1 - 1) * (parseInt(pageSize as string) || 10), - take: parseInt(pageSize as string) || 10, - }); - + const users = await user.fetchUsers(filter, parseInt(page as string) || 1, parseInt(pageSize as string) || 10); res.status(200).json(users); } catch (error) { res.status(500).json({ error: 'Internal Server Error' }); } - } else if (req.method === 'POST') { - try { - const { loginUser } = req.body; - - if (!loginUser) { - return res.status(400).json({ error: 'Missing loginUser data' }); - } - - const createdUser = await prisma.user.create({ - data: { - username: loginUser.email ?? "", - email: loginUser.email ?? "", - name: loginUser.name ?? "", - avatar: loginUser.image ?? undefined, - }, - }); - - res.status(201).json(createdUser); - } catch (error) { - console.error('Error creating user:', error); - res.status(500).json({ error: 'Internal Server Error' }); - } } else { res.status(405).json({ error: 'Method Not Allowed' }); } From 0518d94e87a4d7791435c1c58510e339d791afd5 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Wed, 29 Nov 2023 19:39:39 -0300 Subject: [PATCH 14/30] fix user.dao.ts From 64b5e28d13b214b18c6117d46b8273ace149669b Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Fri, 1 Dec 2023 21:40:49 -0300 Subject: [PATCH 15/30] follow review on user.dao.ts --- src/dao/user.dao.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index 963d251..c445c0a 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -30,15 +30,15 @@ class UserDAO { async fetchUsers( filter: { username?: string; email?: string }, - page: number = 1, + page: number = 0, pageSize: number = 10 ) { const skip = (page - 1) * pageSize; return await prisma.user.findMany({ where: { - username: filter.username ? { contains: filter.username } : undefined, - email: filter.email ? { contains: filter.email } : undefined, + username: filter.username ? { contains: filter.username } : string, + email: filter.email ? { contains: filter.email } : string, }, skip, take: pageSize, From 7c005d2ef5699722ba1bde8bd5221641185e3956 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Thu, 25 Jan 2024 10:12:28 -0300 Subject: [PATCH 16/30] Update user.dao.ts --- src/dao/user.dao.ts | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index c445c0a..1318f56 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -28,22 +28,24 @@ class UserDAO { }); } - async fetchUsers( - filter: { username?: string; email?: string }, - page: number = 0, - pageSize: number = 10 - ) { - const skip = (page - 1) * pageSize; +async fetchUsers( + filter: { username?: string; email?: string }, + page: number = 1, + pageSize: number = 10 +) { + const skip = (page - 1) * pageSize; + const where = {}; + + if (filter.email) where.email = { contains: filter.email }; + if (filter.username) where.username = { contains: filter.username }; + + return await prisma.user.findMany({ + where, + skip, + take: pageSize, + }); +} - return await prisma.user.findMany({ - where: { - username: filter.username ? { contains: filter.username } : string, - email: filter.email ? { contains: filter.email } : string, - }, - skip, - take: pageSize, - }); - } async isOboardingFinished(username: string) { const user = From 450f24bb4cc57f287f7e5cfb0a706923b6a1b173 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Thu, 25 Jan 2024 10:16:51 -0300 Subject: [PATCH 17/30] follow review in route.ts --- src/app/api/users/route.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index b385677..6707453 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -5,21 +5,25 @@ export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - if (req.method === 'GET') { - try { + try { + if (req.method === 'GET') { const { username, email, page, pageSize } = req.query; const filter = { - username: username as string | undefined, - email: email as string | undefined, + username: typeof username === 'string' ? username : undefined, + email: typeof email === 'string' ? email : undefined, }; - const users = await user.fetchUsers(filter, parseInt(page as string) || 1, parseInt(pageSize as string) || 10); + const pageNum = parseInt(page as string, 10); + const size = parseInt(pageSize as string, 10); + + const users = await user.fetchUsers(filter, isNaN(pageNum) ? 1 : pageNum, isNaN(size) ? 10 : size); res.status(200).json(users); - } catch (error) { - res.status(500).json({ error: 'Internal Server Error' }); + } else { + res.setHeader('Allow', ['GET']); + res.status(405).end(`Method ${req.method} Not Allowed`); } - } else { - res.status(405).json({ error: 'Method Not Allowed' }); + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }); } } From 7cd623e4aa0e3c1593458f502ddc6a839ada95ce Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Fri, 26 Jan 2024 10:38:02 -0300 Subject: [PATCH 18/30] fix: route.ts --- src/app/api/users/route.ts | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 6707453..df03dcf 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,29 +1,21 @@ import { user } from "@/dao/user.dao"; import { NextApiRequest, NextApiResponse } from 'next'; -export default async function handler( - req: NextApiRequest, - res: NextApiResponse -) { +export async function GET(req: NextRequest) { try { - if (req.method === 'GET') { - const { username, email, page, pageSize } = req.query; + const { username, email, page, pageSize } = req.query; - const filter = { - username: typeof username === 'string' ? username : undefined, - email: typeof email === 'string' ? email : undefined, - }; + const filter = { + username: typeof username === 'string' ? username : undefined, + email: typeof email === 'string' ? email : undefined, + }; - const pageNum = parseInt(page as string, 10); - const size = parseInt(pageSize as string, 10); + const pageNum = parseInt(page as string, 10); + const size = parseInt(pageSize as string, 10); - const users = await user.fetchUsers(filter, isNaN(pageNum) ? 1 : pageNum, isNaN(size) ? 10 : size); - res.status(200).json(users); - } else { - res.setHeader('Allow', ['GET']); - res.status(405).end(`Method ${req.method} Not Allowed`); - } + const users = await user.fetchUsers(filter, isNaN(pageNum) ? 1 : pageNum, isNaN(size) ? 10 : size); + return NextResponse.json(users); } catch (error) { - res.status(500).json({ error: 'Internal Server Error' }); + return new NextResponse(JSON.stringify({ error: 'Internal Server Error' }), { status: 500 }); } } From 8b8b55cf3a652a49c7265685e7fa0dd435972a94 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Fri, 26 Jan 2024 10:53:30 -0300 Subject: [PATCH 19/30] fix: following Frat's review in user.dao.ts --- src/dao/user.dao.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index 1318f56..23b6d09 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -34,11 +34,18 @@ async fetchUsers( pageSize: number = 10 ) { const skip = (page - 1) * pageSize; - const where = {}; - - if (filter.email) where.email = { contains: filter.email }; - if (filter.username) where.username = { contains: filter.username }; - + const where = { + OR: [] + }; + if (filter.email) { + where.OR.push({ email: { contains: filter.email } }); + } + if (filter.username) { + where.OR.push({ username: { contains: filter.username } }); + } +if (where.OR.length === 0) { + delete where.OR; + } return await prisma.user.findMany({ where, skip, @@ -46,7 +53,6 @@ async fetchUsers( }); } - async isOboardingFinished(username: string) { const user = (await this.fetchUserBy({ username })) ?? From 811d5ae0449dabae0acf6adcea44b0f5863ed5bb Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Fri, 26 Jan 2024 10:57:04 -0300 Subject: [PATCH 20/30] fix: lint in route.ts --- src/app/api/users/route.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index df03dcf..18f96b9 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,7 +1,7 @@ import { user } from "@/dao/user.dao"; -import { NextApiRequest, NextApiResponse } from 'next'; +import { NextApiRequest, NextApiResponse, NextResponse } from 'next'; -export async function GET(req: NextRequest) { +export async function GET(req: NextApiRequest) { try { const { username, email, page, pageSize } = req.query; @@ -10,10 +10,10 @@ export async function GET(req: NextRequest) { email: typeof email === 'string' ? email : undefined, }; - const pageNum = parseInt(page as string, 10); - const size = parseInt(pageSize as string, 10); + const pageNum = page ? parseInt(page as string, 10) : 1; + const size = pageSize ? parseInt(pageSize as string, 10) : 10; - const users = await user.fetchUsers(filter, isNaN(pageNum) ? 1 : pageNum, isNaN(size) ? 10 : size); + const users = await user.fetchUsers(filter, pageNum, size); return NextResponse.json(users); } catch (error) { return new NextResponse(JSON.stringify({ error: 'Internal Server Error' }), { status: 500 }); From 2afd036db34fc21a2078bf383a3a83dfdee8b98d Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Fri, 26 Jan 2024 10:59:27 -0300 Subject: [PATCH 21/30] Fix: lint in user.dao.ts --- src/dao/user.dao.ts | 76 ++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index 23b6d09..0bf228c 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -7,57 +7,57 @@ import { formSchema } from "@/shared/onboarding"; class UserDAO { async createUser(loginUser: NextUser) { - const existingUser = await this.fetchUserBy({ - email: loginUser.email ?? raise("E-mail not found"), - }); + if (!loginUser.email) { + throw raise("E-mail not found"); + } + const existingUser = await this.fetchUserBy({ email: loginUser.email }); if (existingUser) return existingUser; - return await prisma.user.create({ + return prisma.user.create({ data: this.parseNextAuthUser(loginUser), }); } async fetchUserBy(where: Prisma.UserWhereUniqueInput) { - if (where.username) { - where.username = decodeURIComponent(where.username); + const query = { ...where }; + if (query.username) { + query.username = decodeURIComponent(query.username); } - return await prisma.user.findUnique({ - where, - }); + return prisma.user.findUnique({ where: query }); } -async fetchUsers( - filter: { username?: string; email?: string }, - page: number = 1, - pageSize: number = 10 -) { - const skip = (page - 1) * pageSize; - const where = { - OR: [] - }; - if (filter.email) { - where.OR.push({ email: { contains: filter.email } }); - } - if (filter.username) { - where.OR.push({ username: { contains: filter.username } }); - } -if (where.OR.length === 0) { - delete where.OR; + async fetchUsers( + filter: { username?: string; email?: string }, + page: number = 1, + pageSize: number = 10 + ) { + const skip = (page - 1) * pageSize; + const where = { + OR: [] + }; + if (filter.email) { + where.OR.push({ email: { contains: filter.email } }); + } + if (filter.username) { + where.OR.push({ username: { contains: filter.username } }); + } + if (where.OR.length === 0) { + delete where.OR; + } + return prisma.user.findMany({ + where, + skip, + take: pageSize, + }); } - return await prisma.user.findMany({ - where, - skip, - take: pageSize, - }); -} async isOboardingFinished(username: string) { - const user = - (await this.fetchUserBy({ username })) ?? - raise("Could not find user on DB"); - + const user = await this.fetchUserBy({ username }); + if (!user) { + throw raise("Could not find user in DB"); + } return Boolean(user.expectations); } @@ -70,7 +70,7 @@ if (where.OR.length === 0) { data: { socialName: data.registration.nomeSocial, gender: data.registration.gender, - age: parseInt(data.registration.idade), + age: parseInt(data.registration.idade, 10), country: data.contact.pais, city: data.contact.cidadeEstado, phoneNumber: data.contact.telefone, @@ -86,7 +86,7 @@ if (where.OR.length === 0) { } async assignTasksToUser(userId: number, tasks: Task[]) { - const tasksData = tasks.map((task) => ({ + const tasksData = tasks.map(task => ({ userId, taskId: task.id, completed: false, From 5310e4e0d9b9d92d7193c8ae6dea67b3d3785477 Mon Sep 17 00:00:00 2001 From: Luana Nunes Date: Thu, 1 Feb 2024 17:09:21 -0300 Subject: [PATCH 22/30] fix: lint --- src/dao/user.dao.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index 0bf228c..5420e97 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -29,13 +29,13 @@ class UserDAO { } async fetchUsers( - filter: { username?: string; email?: string }, - page: number = 1, - pageSize: number = 10 + filter: { username?: string; email?: string }, + page = 1, + pageSize = 10 ) { const skip = (page - 1) * pageSize; const where = { - OR: [] + OR: [], }; if (filter.email) { where.OR.push({ email: { contains: filter.email } }); @@ -86,7 +86,7 @@ class UserDAO { } async assignTasksToUser(userId: number, tasks: Task[]) { - const tasksData = tasks.map(task => ({ + const tasksData = tasks.map((task) => ({ userId, taskId: task.id, completed: false, From 82cf3cdc274cb0e2a9ccede0d3531babff447292 Mon Sep 17 00:00:00 2001 From: Luana Nunes Date: Thu, 1 Feb 2024 17:24:42 -0300 Subject: [PATCH 23/30] fix: fetchUsers --- src/dao/user.dao.ts | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index 5420e97..e56f8ae 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -34,23 +34,26 @@ class UserDAO { pageSize = 10 ) { const skip = (page - 1) * pageSize; - const where = { - OR: [], - }; - if (filter.email) { - where.OR.push({ email: { contains: filter.email } }); - } - if (filter.username) { - where.OR.push({ username: { contains: filter.username } }); - } - if (where.OR.length === 0) { - delete where.OR; + const where: Prisma.UserWhereInput = {}; + + if (filter.email || filter.username) { + where.OR = []; + + if (filter.email) { + where.OR?.push({ email: { contains: filter.email } }); + } + if (filter.username) { + where.OR?.push({ username: { contains: filter.username } }); + } + if (where.OR?.length === 0) { + delete where.OR; + } + return prisma.user.findMany({ + where: where as Prisma.UserWhereInput, + skip, + take: pageSize, + }); } - return prisma.user.findMany({ - where, - skip, - take: pageSize, - }); } async isOboardingFinished(username: string) { From f71d396d882b9cc7b46380141bcdaaa86c8985a5 Mon Sep 17 00:00:00 2001 From: Luana Nunes Date: Wed, 14 Feb 2024 16:47:56 -0300 Subject: [PATCH 24/30] fix: users route --- src/app/api/users/route.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 18f96b9..9c1e33e 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,21 +1,27 @@ import { user } from "@/dao/user.dao"; -import { NextApiRequest, NextApiResponse, NextResponse } from 'next'; +import { NextApiRequest } from "next"; +import { NextResponse } from "next/server"; export async function GET(req: NextApiRequest) { try { - const { username, email, page, pageSize } = req.query; + const { username, email, page, pageSize } = req.query || {}; const filter = { - username: typeof username === 'string' ? username : undefined, - email: typeof email === 'string' ? email : undefined, + username: typeof username === "string" ? username : undefined, + email: typeof email === "string" ? email : undefined, }; const pageNum = page ? parseInt(page as string, 10) : 1; const size = pageSize ? parseInt(pageSize as string, 10) : 10; const users = await user.fetchUsers(filter, pageNum, size); - return NextResponse.json(users); + return new NextResponse(JSON.stringify(users), { + status: 201, + }); } catch (error) { - return new NextResponse(JSON.stringify({ error: 'Internal Server Error' }), { status: 500 }); + return new NextResponse( + JSON.stringify({ error: "Internal Server Error" }), + { status: 500 } + ); } } From fe176bcc12d4c993769c8785f8c654c71b8004c4 Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Sun, 3 Mar 2024 18:51:48 -0300 Subject: [PATCH 25/30] refactor: route.ts --- src/app/api/users/route.ts | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 9c1e33e..d905dbe 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,27 +1,30 @@ import { user } from "@/dao/user.dao"; -import { NextApiRequest } from "next"; -import { NextResponse } from "next/server"; +import { NextResponse, NextRequest } from "next/server"; +import { z } from "zod"; -export async function GET(req: NextApiRequest) { - try { - const { username, email, page, pageSize } = req.query || {}; +const checkGetAllUsersParams = z.object({ + username: z.string().optional(), + email: z.string().optional(), + page: z.number().optional().transform((val) => (val ? Number(val) : undefined)), + pageSize: z.number().optional().transform((val) => (val ? Number(val) : undefined)), +}); - const filter = { - username: typeof username === "string" ? username : undefined, - email: typeof email === "string" ? email : undefined, - }; +export async function GET(req: NextRequest) { + try { + + const queryParams = checkGetAllUsersParams.parse(Object.fromEntries(req.nextUrl.searchParams)); - const pageNum = page ? parseInt(page as string, 10) : 1; - const size = pageSize ? parseInt(pageSize as string, 10) : 10; + const { username, email, page, pageSize } = queryParams; + + const users = await user.fetchUsers({ username, email }, page, pageSize); - const users = await user.fetchUsers(filter, pageNum, size); return new NextResponse(JSON.stringify(users), { - status: 201, + status: 200, }); } catch (error) { - return new NextResponse( - JSON.stringify({ error: "Internal Server Error" }), - { status: 500 } - ); + console.error(error); + return new NextResponse(JSON.stringify({ error: "Internal Server Error" }), { + status: 500, + }); } } From 2928419574ea7dffc8233dc6c517a4de0fb7b0cf Mon Sep 17 00:00:00 2001 From: Felipe Ogata <82166626+ogatalars@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:09:26 -0300 Subject: [PATCH 26/30] refactor: follow review on route.ts --- src/app/api/users/route.ts | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index d905dbe..778d381 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,30 +1,23 @@ import { user } from "@/dao/user.dao"; -import { NextResponse, NextRequest } from "next/server"; +import { NextResponse } from "next/server"; import { z } from "zod"; -const checkGetAllUsersParams = z.object({ +const DEFAULT_PAGE = 1; +const DEFAULT_PAGE_SIZE = 10; + +const ListAllUsersParamsSchema = z.object({ username: z.string().optional(), email: z.string().optional(), - page: z.number().optional().transform((val) => (val ? Number(val) : undefined)), - pageSize: z.number().optional().transform((val) => (val ? Number(val) : undefined)), + page: z.number().default(DEFAULT_PAGE), + pageSize: z.number().default(DEFAULT_PAGE_SIZE), }); -export async function GET(req: NextRequest) { - try { - - const queryParams = checkGetAllUsersParams.parse(Object.fromEntries(req.nextUrl.searchParams)); +export async function GET(req) { + const queryParams = ListAllUsersParamsSchema.parse(Object.fromEntries(req.nextUrl.searchParams)); + + const { username, email, page, pageSize } = queryParams; - const { username, email, page, pageSize } = queryParams; - - const users = await user.fetchUsers({ username, email }, page, pageSize); + const users = await user.fetchUsers({ username, email }, page, pageSize); - return new NextResponse(JSON.stringify(users), { - status: 200, - }); - } catch (error) { - console.error(error); - return new NextResponse(JSON.stringify({ error: "Internal Server Error" }), { - status: 500, - }); - } + return NextResponse.json(users); } From 2ef45ddfd435e3756da3543172c76525aa1a0416 Mon Sep 17 00:00:00 2001 From: Pedro Frattezi Silva Date: Wed, 6 Mar 2024 08:10:19 -0300 Subject: [PATCH 27/30] revert: user dao changes --- src/dao/user.dao.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index e56f8ae..f2fa93b 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -7,25 +7,25 @@ import { formSchema } from "@/shared/onboarding"; class UserDAO { async createUser(loginUser: NextUser) { - if (!loginUser.email) { - throw raise("E-mail not found"); - } - const existingUser = await this.fetchUserBy({ email: loginUser.email }); + const existingUser = await this.fetchUserBy({ + email: loginUser.email ?? raise("E-mail not found"), + }); if (existingUser) return existingUser; - return prisma.user.create({ + return await prisma.user.create({ data: this.parseNextAuthUser(loginUser), }); } async fetchUserBy(where: Prisma.UserWhereUniqueInput) { - const query = { ...where }; - if (query.username) { - query.username = decodeURIComponent(query.username); + if (where.username) { + where.username = decodeURIComponent(where.username); } - return prisma.user.findUnique({ where: query }); + return await prisma.user.findUnique({ + where, + }); } async fetchUsers( @@ -57,10 +57,10 @@ class UserDAO { } async isOboardingFinished(username: string) { - const user = await this.fetchUserBy({ username }); - if (!user) { - throw raise("Could not find user in DB"); - } + const user = + (await this.fetchUserBy({ username })) ?? + raise("Could not find user on DB"); + return Boolean(user.expectations); } @@ -73,7 +73,7 @@ class UserDAO { data: { socialName: data.registration.nomeSocial, gender: data.registration.gender, - age: parseInt(data.registration.idade, 10), + age: parseInt(data.registration.idade), country: data.contact.pais, city: data.contact.cidadeEstado, phoneNumber: data.contact.telefone, From b6708e4a00ee04b447d73294f179a5b7c7463616 Mon Sep 17 00:00:00 2001 From: Pedro Frattezi Silva Date: Wed, 6 Mar 2024 20:00:34 -0300 Subject: [PATCH 28/30] fix: update user dao for fetch all users --- src/app/api/users/route.ts | 13 ++++++++----- src/dao/user.dao.ts | 37 +++++++++++++++++-------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 778d381..4c01092 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,19 +1,22 @@ import { user } from "@/dao/user.dao"; -import { NextResponse } from "next/server"; +import { NextResponse, NextRequest } from "next/server"; import { z } from "zod"; const DEFAULT_PAGE = 1; const DEFAULT_PAGE_SIZE = 10; const ListAllUsersParamsSchema = z.object({ + name: z.string().optional(), username: z.string().optional(), email: z.string().optional(), - page: z.number().default(DEFAULT_PAGE), - pageSize: z.number().default(DEFAULT_PAGE_SIZE), + page: z.coerce.number().default(DEFAULT_PAGE), + pageSize: z.coerce.number().default(DEFAULT_PAGE_SIZE), }); -export async function GET(req) { - const queryParams = ListAllUsersParamsSchema.parse(Object.fromEntries(req.nextUrl.searchParams)); +export async function GET(req: NextRequest) { + const queryParams = ListAllUsersParamsSchema.parse( + Object.fromEntries(req.nextUrl.searchParams) + ); const { username, email, page, pageSize } = queryParams; diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index f2fa93b..57053c0 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -34,26 +34,23 @@ class UserDAO { pageSize = 10 ) { const skip = (page - 1) * pageSize; - const where: Prisma.UserWhereInput = {}; - - if (filter.email || filter.username) { - where.OR = []; - - if (filter.email) { - where.OR?.push({ email: { contains: filter.email } }); - } - if (filter.username) { - where.OR?.push({ username: { contains: filter.username } }); - } - if (where.OR?.length === 0) { - delete where.OR; - } - return prisma.user.findMany({ - where: where as Prisma.UserWhereInput, - skip, - take: pageSize, - }); - } + const hasFilters = Object.values(filter).some((value) => value); + + const whereCondition = [{ + email: { contains: filter.email }, + }, { + username: { contains: filter.username }, + },]; + + const where: Prisma.UserWhereInput = { + OR: hasFilters ? whereCondition : undefined, + }; + + return prisma.user.findMany({ + where: where, + skip, + take: pageSize, + }); } async isOboardingFinished(username: string) { From 472b9427a62dd27bacb2efcd6a68c15a1a03a84b Mon Sep 17 00:00:00 2001 From: Pedro Frattezi Silva Date: Fri, 8 Mar 2024 19:21:01 -0300 Subject: [PATCH 29/30] feat: create pagination shared zod validation --- src/shared/pagination.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/shared/pagination.ts diff --git a/src/shared/pagination.ts b/src/shared/pagination.ts new file mode 100644 index 0000000..57c7593 --- /dev/null +++ b/src/shared/pagination.ts @@ -0,0 +1,9 @@ +import { z } from "zod"; + +const DEFAULT_PAGE = 1; +const DEFAULT_PAGE_SIZE = 10; + +export const PaginationParamsSchema = z.object({ + page: z.coerce.number().min(1).default(DEFAULT_PAGE), + pageSize: z.coerce.number().min(10).max(100).default(DEFAULT_PAGE_SIZE), +}); From 85ac5287e8f8ee5e79dc7af2f4c66e0264c7919c Mon Sep 17 00:00:00 2001 From: Pedro Frattezi Silva Date: Fri, 8 Mar 2024 19:22:12 -0300 Subject: [PATCH 30/30] feat: enhance validation and filter conditions for get users endpoint --- src/app/api/users/route.ts | 22 +++++++++--------- src/dao/user.dao.ts | 46 +++++++++++++++++++++++++------------- src/entities/users.ts | 8 ++++++- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 4c01092..a07a6d3 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,26 +1,24 @@ import { user } from "@/dao/user.dao"; +import { PaginationParamsSchema } from "@/shared/pagination"; import { NextResponse, NextRequest } from "next/server"; import { z } from "zod"; -const DEFAULT_PAGE = 1; -const DEFAULT_PAGE_SIZE = 10; - -const ListAllUsersParamsSchema = z.object({ - name: z.string().optional(), - username: z.string().optional(), - email: z.string().optional(), - page: z.coerce.number().default(DEFAULT_PAGE), - pageSize: z.coerce.number().default(DEFAULT_PAGE_SIZE), -}); +const ListAllUsersParamsSchema = z + .object({ + name: z.string().optional(), + username: z.string().optional(), + email: z.string().optional(), + }) + .merge(PaginationParamsSchema); export async function GET(req: NextRequest) { const queryParams = ListAllUsersParamsSchema.parse( Object.fromEntries(req.nextUrl.searchParams) ); - const { username, email, page, pageSize } = queryParams; + const { page, pageSize, ...filters } = queryParams; - const users = await user.fetchUsers({ username, email }, page, pageSize); + const users = await user.fetchUsers(filters, page, pageSize); return NextResponse.json(users); } diff --git a/src/dao/user.dao.ts b/src/dao/user.dao.ts index 57053c0..111185f 100644 --- a/src/dao/user.dao.ts +++ b/src/dao/user.dao.ts @@ -4,6 +4,7 @@ import { z } from "zod"; import { prisma } from "./client"; import { raise } from "@/shared/exceptions"; import { formSchema } from "@/shared/onboarding"; +import { GetUsers } from "@/entities/users"; class UserDAO { async createUser(loginUser: NextUser) { @@ -28,29 +29,42 @@ class UserDAO { }); } - async fetchUsers( - filter: { username?: string; email?: string }, - page = 1, - pageSize = 10 - ) { + async fetchUsers(filter: GetUsers, page = 1, pageSize = 10) { const skip = (page - 1) * pageSize; - const hasFilters = Object.values(filter).some((value) => value); + const whereCondition: Prisma.Enumerable = []; - const whereCondition = [{ - email: { contains: filter.email }, - }, { - username: { contains: filter.username }, - },]; + Object.keys(filter).forEach((key) => { + const property = key as keyof typeof filter; + const value = filter[property]; - const where: Prisma.UserWhereInput = { - OR: hasFilters ? whereCondition : undefined, - }; + if (value !== undefined) { + whereCondition.push({ + [key]: { contains: value, mode: "insensitive" }, + }); + } + }); - return prisma.user.findMany({ + let where: Prisma.UserWhereInput = {}; + if (whereCondition.length > 0) { + where = { OR: whereCondition }; + } + + const [users, total] = await prisma.$transaction([prisma.user.findMany({ where: where, skip, take: pageSize, - }); + }), prisma.user.count({ + where: where, + }),]); + + return { + total, + data: users, + pagination: { + page, + pageSize, + }, + }; } async isOboardingFinished(username: string) { diff --git a/src/entities/users.ts b/src/entities/users.ts index 794df3b..142a21d 100644 --- a/src/entities/users.ts +++ b/src/entities/users.ts @@ -1,11 +1,17 @@ import { Session } from "next-auth"; - +import { User as UserEntity } from "@prisma/client"; export type User = { name: string; email: string; image: string; }; +export type GetUsers = { + name?: UserEntity["name"]; + email?: UserEntity["email"]; + username?: UserEntity["username"]; +}; + export function getUserSession(session: Session | null): User { if (session?.user == null) { throw new Error("User session not found");