diff --git a/apps/nextjs-app/e2e/tests/auth.setup.ts b/apps/nextjs-app/e2e/tests/auth.setup.ts
index 187d10c9..1117cc38 100644
--- a/apps/nextjs-app/e2e/tests/auth.setup.ts
+++ b/apps/nextjs-app/e2e/tests/auth.setup.ts
@@ -28,7 +28,7 @@ setup('authenticate', async ({ page }) => {
// log out:
await page.getByRole('button', { name: 'Open user menu' }).click();
await page.getByRole('menuitem', { name: 'Sign Out' }).click();
- await page.waitForURL('/auth/login?redirectTo=%252Fapp');
+ await page.waitForURL('/auth/login?redirectTo=%2Fapp');
// log in:
await page.getByLabel('Email Address').click();
diff --git a/apps/nextjs-app/mock-server.ts b/apps/nextjs-app/mock-server.ts
index 8e217267..d2eae318 100644
--- a/apps/nextjs-app/mock-server.ts
+++ b/apps/nextjs-app/mock-server.ts
@@ -16,7 +16,19 @@ app.use(
);
app.use(express.json());
-app.use(logger({ level: 'silent' }));
+app.use(
+ logger({
+ level: 'info',
+ redact: ['req.headers', 'res.headers'],
+ transport: {
+ target: 'pino-pretty',
+ options: {
+ colorize: true,
+ translateTime: true,
+ },
+ },
+ }),
+);
app.use(createMiddleware(...handlers));
initializeDb().then(() => {
diff --git a/apps/nextjs-app/package.json b/apps/nextjs-app/package.json
index ea64edf2..d5dcce00 100644
--- a/apps/nextjs-app/package.json
+++ b/apps/nextjs-app/package.json
@@ -42,7 +42,6 @@
"react-dom": "^18.3.1",
"react-error-boundary": "^4.0.13",
"react-hook-form": "^7.51.3",
- "react-query-auth": "^2.3.0",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.4",
@@ -109,7 +108,7 @@
"tsx": "^4.17.0",
"typescript": "^5.4.5",
"vite-tsconfig-paths": "^4.3.2",
- "vitest": "^1.5.2"
+ "vitest": "^2.1.4"
},
"msw": {
"workerDirectory": "public"
diff --git a/apps/nextjs-app/src/app/app/_components/dashboard-info.tsx b/apps/nextjs-app/src/app/app/_components/dashboard-info.tsx
new file mode 100644
index 00000000..92b6be5c
--- /dev/null
+++ b/apps/nextjs-app/src/app/app/_components/dashboard-info.tsx
@@ -0,0 +1,34 @@
+'use client';
+
+import { useUser } from '@/lib/auth';
+
+export const DashboardInfo = () => {
+ const user = useUser();
+
+ return (
+ <>
+
+ Welcome {`${user.data?.firstName} ${user.data?.lastName}`}
+
+
+ Your role is : {user.data?.role}
+
+ In this application you can:
+ {user.data?.role === 'USER' && (
+
+ Create comments in discussions
+ Delete own comments
+
+ )}
+ {user.data?.role === 'ADMIN' && (
+
+ Create discussions
+ Edit discussions
+ Delete discussions
+ Comment on discussions
+ Delete all comments
+
+ )}
+ >
+ );
+};
diff --git a/apps/nextjs-app/src/components/layouts/dashboard-layout.tsx b/apps/nextjs-app/src/app/app/_components/dashboard-layout.tsx
similarity index 84%
rename from apps/nextjs-app/src/components/layouts/dashboard-layout.tsx
rename to apps/nextjs-app/src/app/app/_components/dashboard-layout.tsx
index 1c27b906..a84797b6 100644
--- a/apps/nextjs-app/src/components/layouts/dashboard-layout.tsx
+++ b/apps/nextjs-app/src/app/app/_components/dashboard-layout.tsx
@@ -3,25 +3,21 @@
import { Home, PanelLeft, Folder, Users, User2 } from 'lucide-react';
import NextLink from 'next/link';
import { useRouter, usePathname } from 'next/navigation';
-import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { Button } from '@/components/ui/button';
import { Drawer, DrawerContent, DrawerTrigger } from '@/components/ui/drawer';
-import { Spinner } from '@/components/ui/spinner';
-import { paths } from '@/config/paths';
-import { AuthLoader, useLogout } from '@/lib/auth';
-import { ROLES, useAuthorization } from '@/lib/authorization';
-import { cn } from '@/utils/cn';
-
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
-} from '../ui/dropdown';
-import { Link } from '../ui/link';
+} from '@/components/ui/dropdown';
+import { Link } from '@/components/ui/link';
+import { paths } from '@/config/paths';
+import { useLogout, useUser } from '@/lib/auth';
+import { cn } from '@/utils/cn';
type SideNavigationItem = {
name: string;
@@ -41,14 +37,16 @@ const Logo = () => {
};
const Layout = ({ children }: { children: React.ReactNode }) => {
- const logout = useLogout();
- const { checkAccess } = useAuthorization();
+ const user = useUser();
const pathname = usePathname();
const router = useRouter();
+ const logout = useLogout({
+ onSuccess: () => router.push(paths.auth.login.getHref(pathname)),
+ });
const navigation = [
{ name: 'Dashboard', to: paths.app.root.getHref(), icon: Home },
{ name: 'Discussions', to: paths.app.discussions.getHref(), icon: Folder },
- checkAccess({ allowedRoles: [ROLES.ADMIN] }) && {
+ user.data?.role === 'ADMIN' && {
name: 'Users',
to: paths.app.users.getHref(),
icon: Users,
@@ -152,7 +150,7 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
logout.mutate({})}
+ onClick={() => logout.mutate()}
>
Sign Out
@@ -167,6 +165,10 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
);
};
+function Fallback({ error }: { error: Error }) {
+ return Error: {error.message ?? 'Something went wrong!'}
;
+}
+
export const DashboardLayout = ({
children,
}: {
@@ -175,28 +177,9 @@ export const DashboardLayout = ({
const pathname = usePathname();
return (
-
-
-
- }
- >
- Something went wrong!}
- >
- (
-
-
-
- )}
- >
- {children}
-
-
-
+
+ {children}
+
);
};
diff --git a/apps/nextjs-app/src/app/app/discussions/[discussionId]/__tests__/discussion.test.tsx b/apps/nextjs-app/src/app/app/discussions/[discussionId]/__tests__/discussion.test.tsx
index c0e0e15e..30332bb3 100644
--- a/apps/nextjs-app/src/app/app/discussions/[discussionId]/__tests__/discussion.test.tsx
+++ b/apps/nextjs-app/src/app/app/discussions/[discussionId]/__tests__/discussion.test.tsx
@@ -11,7 +11,7 @@ import {
waitForLoadingToFinish,
} from '@/testing/test-utils';
-import DiscussionPage from '../page';
+import { Discussion } from '../_components/discussion';
vi.mock('next/navigation', async () => {
const actual = await vi.importActual('next/navigation');
@@ -33,11 +33,14 @@ const renderDiscussion = async () => {
vi.mocked(useParams).mockReturnValue({ discussionId: fakeDiscussion.id });
- const utils = await renderApp( , {
- user: fakeUser,
- path: `/app/discussions/:discussionId`,
- url: `/app/discussions/${fakeDiscussion.id}`,
- });
+ const utils = await renderApp(
+ ,
+ {
+ user: fakeUser,
+ path: `/app/discussions/:discussionId`,
+ url: `/app/discussions/${fakeDiscussion.id}`,
+ },
+ );
await waitForLoadingToFinish();
diff --git a/apps/nextjs-app/src/app/app/discussions/[discussionId]/_components/discussion.tsx b/apps/nextjs-app/src/app/app/discussions/[discussionId]/_components/discussion.tsx
new file mode 100644
index 00000000..e64d267d
--- /dev/null
+++ b/apps/nextjs-app/src/app/app/discussions/[discussionId]/_components/discussion.tsx
@@ -0,0 +1,27 @@
+'use client';
+
+import { ErrorBoundary } from 'react-error-boundary';
+
+import { ContentLayout } from '@/components/layouts/content-layout';
+import { Comments } from '@/features/comments/components/comments';
+import { useDiscussion } from '@/features/discussions/api/get-discussion';
+import { DiscussionView } from '@/features/discussions/components/discussion-view';
+
+export const Discussion = ({ discussionId }: { discussionId: string }) => {
+ const discussion = useDiscussion({ discussionId });
+
+ return (
+
+
+
+ Failed to load comments. Try to refresh the page.
+ }
+ >
+
+
+
+
+ );
+};
diff --git a/apps/nextjs-app/src/app/app/discussions/[discussionId]/page.tsx b/apps/nextjs-app/src/app/app/discussions/[discussionId]/page.tsx
index d843e967..e92ce448 100644
--- a/apps/nextjs-app/src/app/app/discussions/[discussionId]/page.tsx
+++ b/apps/nextjs-app/src/app/app/discussions/[discussionId]/page.tsx
@@ -1,47 +1,71 @@
-'use client';
+import {
+ dehydrate,
+ HydrationBoundary,
+ QueryClient,
+} from '@tanstack/react-query';
-import { useParams } from 'next/navigation';
-import { ErrorBoundary } from 'react-error-boundary';
+import { getInfiniteCommentsQueryOptions } from '@/features/comments/api/get-comments';
+import {
+ getDiscussion,
+ getDiscussionQueryOptions,
+} from '@/features/discussions/api/get-discussion';
-import { ContentLayout } from '@/components/layouts/content-layout';
-import { Spinner } from '@/components/ui/spinner';
-import { Comments } from '@/features/comments/components/comments';
-import { useDiscussion } from '@/features/discussions/api/get-discussion';
-import { DiscussionView } from '@/features/discussions/components/discussion-view';
+import { Discussion } from './_components/discussion';
-const DiscussionPage = () => {
- const params = useParams();
- const discussionId = params?.discussionId as string;
+export const generateMetadata = async ({
+ params,
+}: {
+ params: Promise<{ discussionId: string }>;
+}) => {
+ const discussionId = (await params).discussionId;
- const discussionQuery = useDiscussion({
- discussionId,
- });
+ const discussion = await getDiscussion({ discussionId });
- if (discussionQuery.isLoading) {
- return (
-
-
-
- );
- }
+ return {
+ title: discussion.data?.title,
+ description: discussion.data?.title,
+ };
+};
+
+const preloadData = async (discussionId: string) => {
+ const queryClient = new QueryClient();
+
+ await Promise.all([
+ queryClient.prefetchQuery(getDiscussionQueryOptions(discussionId)),
+ queryClient.prefetchInfiniteQuery(
+ getInfiniteCommentsQueryOptions(discussionId),
+ ),
+ ]);
- const discussion = discussionQuery.data?.data;
+ const dehydratedState = dehydrate(queryClient);
+
+ return {
+ dehydratedState,
+ queryClient,
+ };
+};
+
+const DiscussionPage = async ({
+ params,
+}: {
+ params: Promise<{
+ discussionId: string;
+ }>;
+}) => {
+ const discussionId = (await params).discussionId;
+
+ const { dehydratedState, queryClient } = await preloadData(discussionId);
+
+ const discussion = queryClient.getQueryData(
+ getDiscussionQueryOptions(discussionId).queryKey,
+ );
- if (!discussion) return null;
+ if (!discussion?.data) return Discussion not found
;
return (
-
-
-
- Failed to load comments. Try to refresh the page.
- }
- >
-
-
-
-
+
+
+
);
};
diff --git a/apps/nextjs-app/src/app/app/discussions/__tests__/discussions.test.tsx b/apps/nextjs-app/src/app/app/discussions/__tests__/discussions.test.tsx
index b94e3219..880ffdfb 100644
--- a/apps/nextjs-app/src/app/app/discussions/__tests__/discussions.test.tsx
+++ b/apps/nextjs-app/src/app/app/discussions/__tests__/discussions.test.tsx
@@ -11,7 +11,7 @@ import {
} from '@/testing/test-utils';
import { formatDate } from '@/utils/format';
-import DiscussionsPage from '../page';
+import { Discussions } from '../_components/discussions';
beforeAll(() => {
vi.spyOn(console, 'error').mockImplementation(() => {});
@@ -25,7 +25,7 @@ test(
'should create, render and delete discussions',
{ timeout: 10000 },
async () => {
- await renderApp( );
+ await renderApp( );
await waitForLoadingToFinish();
diff --git a/apps/nextjs-app/src/app/app/discussions/_components/discussions.tsx b/apps/nextjs-app/src/app/app/discussions/_components/discussions.tsx
new file mode 100644
index 00000000..82adeba6
--- /dev/null
+++ b/apps/nextjs-app/src/app/app/discussions/_components/discussions.tsx
@@ -0,0 +1,30 @@
+'use client';
+
+import { useQueryClient } from '@tanstack/react-query';
+
+import { ContentLayout } from '@/components/layouts/content-layout';
+import { getInfiniteCommentsQueryOptions } from '@/features/comments/api/get-comments';
+import { CreateDiscussion } from '@/features/discussions/components/create-discussion';
+import { DiscussionsList } from '@/features/discussions/components/discussions-list';
+
+export const Discussions = () => {
+ const queryClient = useQueryClient();
+
+ return (
+
+
+
+
+
+ {
+ // Prefetch the comments data when the user hovers over the link in the list
+ queryClient.prefetchInfiniteQuery(
+ getInfiniteCommentsQueryOptions(id),
+ );
+ }}
+ />
+
+
+ );
+};
diff --git a/apps/nextjs-app/src/app/app/discussions/page.tsx b/apps/nextjs-app/src/app/app/discussions/page.tsx
index bc002009..c1391196 100644
--- a/apps/nextjs-app/src/app/app/discussions/page.tsx
+++ b/apps/nextjs-app/src/app/app/discussions/page.tsx
@@ -1,31 +1,37 @@
-'use client';
+import {
+ dehydrate,
+ HydrationBoundary,
+ QueryClient,
+} from '@tanstack/react-query';
-import { useQueryClient } from '@tanstack/react-query';
+import { getDiscussionsQueryOptions } from '@/features/discussions/api/get-discussions';
-import { ContentLayout } from '@/components/layouts/content-layout';
-import { getInfiniteCommentsQueryOptions } from '@/features/comments/api/get-comments';
-import { CreateDiscussion } from '@/features/discussions/components/create-discussion';
-import { DiscussionsList } from '@/features/discussions/components/discussions-list';
+import { Discussions } from './_components/discussions';
-const DiscussionsPage = () => {
- const queryClient = useQueryClient();
+export const metadata = {
+ title: 'Discussions',
+ description: 'Discussions',
+};
+
+const DiscussionsPage = async ({
+ searchParams,
+}: {
+ searchParams: { page: string | null };
+}) => {
+ const queryClient = new QueryClient();
+
+ await queryClient.prefetchQuery(
+ getDiscussionsQueryOptions({
+ page: searchParams.page ? Number(searchParams.page) : 1,
+ }),
+ );
+
+ const dehydratedState = dehydrate(queryClient);
return (
-
-
-
-
-
- {
- // Prefetch the comments data when the user hovers over the link in the list
- queryClient.prefetchInfiniteQuery(
- getInfiniteCommentsQueryOptions(id),
- );
- }}
- />
-
-
+
+
+
);
};
diff --git a/apps/nextjs-app/src/app/app/layout.tsx b/apps/nextjs-app/src/app/app/layout.tsx
index 4c96e848..2089a6ef 100644
--- a/apps/nextjs-app/src/app/app/layout.tsx
+++ b/apps/nextjs-app/src/app/app/layout.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react';
-import { DashboardLayout } from '@/components/layouts/dashboard-layout';
+import { DashboardLayout } from './_components/dashboard-layout';
export const metadata = {
title: 'Dashboard',
diff --git a/apps/nextjs-app/src/app/app/page.tsx b/apps/nextjs-app/src/app/app/page.tsx
index 6b68bea3..ae67926f 100644
--- a/apps/nextjs-app/src/app/app/page.tsx
+++ b/apps/nextjs-app/src/app/app/page.tsx
@@ -1,37 +1,12 @@
-'use client';
+import { DashboardInfo } from './_components/dashboard-info';
-import { useUser } from '@/lib/auth';
-import { ROLES } from '@/lib/authorization';
-
-const DashboardPage = () => {
- const user = useUser();
+export const metadata = {
+ title: 'Dashboard',
+ description: 'Dashboard',
+};
- return (
- <>
-
- Welcome {`${user.data?.firstName} ${user.data?.lastName}`}
-
-
- Your role is : {user.data?.role}
-
- In this application you can:
- {user.data?.role === ROLES.USER && (
-
- Create comments in discussions
- Delete own comments
-
- )}
- {user.data?.role === ROLES.ADMIN && (
-
- Create discussions
- Edit discussions
- Delete discussions
- Comment on discussions
- Delete all comments
-
- )}
- >
- );
+const DashboardPage = async () => {
+ return ;
};
export default DashboardPage;
diff --git a/apps/nextjs-app/src/app/app/profile/_components/profile.tsx b/apps/nextjs-app/src/app/app/profile/_components/profile.tsx
new file mode 100644
index 00000000..e9b25ecc
--- /dev/null
+++ b/apps/nextjs-app/src/app/app/profile/_components/profile.tsx
@@ -0,0 +1,48 @@
+'use client';
+
+import { UpdateProfile } from '@/features/users/components/update-profile';
+import { useUser } from '@/lib/auth';
+
+type EntryProps = {
+ label: string;
+ value: string;
+};
+const Entry = ({ label, value }: EntryProps) => (
+
+
{label}
+
+ {value}
+
+
+);
+
+export const Profile = () => {
+ const user = useUser();
+
+ if (!user) return null;
+
+ return (
+
+
+
+
+ User Information
+
+
+
+
+ Personal details of the user.
+
+
+
+
+ );
+};
diff --git a/apps/nextjs-app/src/app/app/profile/page.tsx b/apps/nextjs-app/src/app/app/profile/page.tsx
index 198064b6..ed893ca3 100644
--- a/apps/nextjs-app/src/app/app/profile/page.tsx
+++ b/apps/nextjs-app/src/app/app/profile/page.tsx
@@ -1,50 +1,12 @@
-'use client';
+import { Profile } from './_components/profile';
-import { UpdateProfile } from '@/features/users/components/update-profile';
-import { useUser } from '@/lib/auth';
-
-type EntryProps = {
- label: string;
- value: string;
+export const metadata = {
+ title: 'Profile',
+ description: 'Profile',
};
-const Entry = ({ label, value }: EntryProps) => (
-
-
{label}
-
- {value}
-
-
-);
const ProfilePage = () => {
- const user = useUser();
-
- if (!user.data) return null;
-
- return (
-
-
-
-
- User Information
-
-
-
-
- Personal details of the user.
-
-
-
-
- );
+ return ;
};
export default ProfilePage;
diff --git a/apps/nextjs-app/src/app/app/users/_components/admin-guard.tsx b/apps/nextjs-app/src/app/app/users/_components/admin-guard.tsx
new file mode 100644
index 00000000..690157e5
--- /dev/null
+++ b/apps/nextjs-app/src/app/app/users/_components/admin-guard.tsx
@@ -0,0 +1,19 @@
+'use client';
+
+import { Spinner } from '@/components/ui/spinner';
+import { useUser } from '@/lib/auth';
+import { canViewUsers } from '@/lib/authorization';
+
+export const AdminGuard = ({ children }: { children: React.ReactNode }) => {
+ const user = useUser();
+
+ if (!user?.data) {
+ return ;
+ }
+
+ if (!canViewUsers(user?.data)) {
+ return Only admin can view this.
;
+ }
+
+ return children;
+};
diff --git a/apps/nextjs-app/src/app/app/users/_components/users.tsx b/apps/nextjs-app/src/app/app/users/_components/users.tsx
new file mode 100644
index 00000000..669b40df
--- /dev/null
+++ b/apps/nextjs-app/src/app/app/users/_components/users.tsx
@@ -0,0 +1,22 @@
+import {
+ dehydrate,
+ HydrationBoundary,
+ QueryClient,
+} from '@tanstack/react-query';
+
+import { getUsersQueryOptions } from '@/features/users/api/get-users';
+import { UsersList } from '@/features/users/components/users-list';
+
+export const Users = async () => {
+ const queryClient = new QueryClient();
+
+ await queryClient.prefetchQuery(getUsersQueryOptions());
+
+ const dehydratedState = dehydrate(queryClient);
+
+ return (
+
+
+
+ );
+};
diff --git a/apps/nextjs-app/src/app/app/users/page.tsx b/apps/nextjs-app/src/app/app/users/page.tsx
index c6693e06..db32a2fb 100644
--- a/apps/nextjs-app/src/app/app/users/page.tsx
+++ b/apps/nextjs-app/src/app/app/users/page.tsx
@@ -1,18 +1,19 @@
-'use client';
-
import { ContentLayout } from '@/components/layouts/content-layout';
-import { UsersList } from '@/features/users/components/users-list';
-import { Authorization, ROLES } from '@/lib/authorization';
+
+import { AdminGuard } from './_components/admin-guard';
+import { Users } from './_components/users';
+
+export const metadata = {
+ title: 'Users',
+ description: 'Users',
+};
const UsersPage = () => {
return (
- Only admin can view this.}
- allowedRoles={[ROLES.ADMIN]}
- >
-
-
+
+
+
);
};
diff --git a/apps/nextjs-app/src/components/layouts/auth-layout.tsx b/apps/nextjs-app/src/app/auth/_components/auth-layout.tsx
similarity index 100%
rename from apps/nextjs-app/src/components/layouts/auth-layout.tsx
rename to apps/nextjs-app/src/app/auth/_components/auth-layout.tsx
diff --git a/apps/nextjs-app/src/app/auth/layout.tsx b/apps/nextjs-app/src/app/auth/layout.tsx
index 6ee7609b..d0afb440 100644
--- a/apps/nextjs-app/src/app/auth/layout.tsx
+++ b/apps/nextjs-app/src/app/auth/layout.tsx
@@ -1,9 +1,10 @@
import { ReactNode, Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
-import { AuthLayout as AuthLayoutComponent } from '@/components/layouts/auth-layout';
import { Spinner } from '@/components/ui/spinner';
+import { AuthLayout as AuthLayoutComponent } from './_components/auth-layout';
+
export const metadata = {
title: 'Bulletproof React',
description: 'Welcome to Bulletproof React',
diff --git a/apps/nextjs-app/src/app/auth/login/page.tsx b/apps/nextjs-app/src/app/auth/login/page.tsx
index fcdfff01..0ffd05da 100644
--- a/apps/nextjs-app/src/app/auth/login/page.tsx
+++ b/apps/nextjs-app/src/app/auth/login/page.tsx
@@ -5,11 +5,6 @@ import { useRouter, useSearchParams } from 'next/navigation';
import { paths } from '@/config/paths';
import { LoginForm } from '@/features/auth/components/login-form';
-// export const metadata = {
-// title: 'Log in to your account',
-// description: 'Log in to your account',
-// };
-
const LoginPage = () => {
const router = useRouter();
const searchParams = useSearchParams();
diff --git a/apps/nextjs-app/src/app/auth/register/page.tsx b/apps/nextjs-app/src/app/auth/register/page.tsx
index aed4c1cb..99761c3b 100644
--- a/apps/nextjs-app/src/app/auth/register/page.tsx
+++ b/apps/nextjs-app/src/app/auth/register/page.tsx
@@ -7,11 +7,6 @@ import { paths } from '@/config/paths';
import { RegisterForm } from '@/features/auth/components/register-form';
import { useTeams } from '@/features/teams/api/get-teams';
-// export const metadata = {
-// title: 'Register your account',
-// description: 'Register your account',
-// };
-
const RegisterPage = () => {
const router = useRouter();
diff --git a/apps/nextjs-app/src/app/layout.tsx b/apps/nextjs-app/src/app/layout.tsx
index 4b9bc9eb..6bafa239 100644
--- a/apps/nextjs-app/src/app/layout.tsx
+++ b/apps/nextjs-app/src/app/layout.tsx
@@ -1,6 +1,12 @@
+import {
+ dehydrate,
+ HydrationBoundary,
+ QueryClient,
+} from '@tanstack/react-query';
import { ReactNode } from 'react';
import { AppProvider } from '@/app/provider';
+import { getUserQueryOptions } from '@/lib/auth';
import '@/styles/globals.css';
@@ -9,14 +15,28 @@ export const metadata = {
description: 'Showcasing Best Practices For Building React Applications',
};
-const RootLayout = ({ children }: { children: ReactNode }) => {
+const RootLayout = async ({ children }: { children: ReactNode }) => {
+ const queryClient = new QueryClient();
+
+ await queryClient.prefetchQuery(getUserQueryOptions());
+
+ const dehydratedState = dehydrate(queryClient);
+
return (
- {children}
+
+
+ {children}
+
+
);
};
export default RootLayout;
+
+// We are not prerendering anything because the app is highly dynamic
+// and the data depends on the user so we need to send cookies with each request
+export const dynamic = 'force-dynamic';
diff --git a/apps/nextjs-app/src/app/public/discussions/[discussionId]/page.tsx b/apps/nextjs-app/src/app/public/discussions/[discussionId]/page.tsx
index 532d05b5..92ffcb34 100644
--- a/apps/nextjs-app/src/app/public/discussions/[discussionId]/page.tsx
+++ b/apps/nextjs-app/src/app/public/discussions/[discussionId]/page.tsx
@@ -4,7 +4,7 @@ import {
QueryClient,
} from '@tanstack/react-query';
-import DiscussionPage from '@/app/app/discussions/[discussionId]/page';
+import { Discussion } from '@/app/app/discussions/[discussionId]/_components/discussion';
import { getInfiniteCommentsQueryOptions } from '@/features/comments/api/get-comments';
import {
getDiscussion,
@@ -14,26 +14,27 @@ import {
export const generateMetadata = async ({
params,
}: {
- params: { discussionId: string };
+ params: Promise<{ discussionId: string }>;
}) => {
- const discussion = await getDiscussion({
- discussionId: params.discussionId,
- });
+ const discussionId = (await params).discussionId;
- const name = discussion.data.title;
+ const discussion = await getDiscussion({ discussionId });
return {
- title: name,
+ title: discussion.data?.title,
+ description: discussion.data?.title,
};
};
const preloadData = async (discussionId: string) => {
const queryClient = new QueryClient();
- await queryClient.prefetchQuery(getDiscussionQueryOptions(discussionId));
- await queryClient.prefetchInfiniteQuery(
- getInfiniteCommentsQueryOptions(discussionId),
- );
+ await Promise.all([
+ queryClient.prefetchQuery(getDiscussionQueryOptions(discussionId)),
+ queryClient.prefetchInfiniteQuery(
+ getInfiniteCommentsQueryOptions(discussionId),
+ ),
+ ]);
return {
dehydratedState: dehydrate(queryClient),
@@ -50,7 +51,7 @@ const PublicDiscussionPage = async ({
const { dehydratedState } = await preloadData(discussionId);
return (
-
+
);
};
diff --git a/apps/nextjs-app/src/components/layouts/content-layout.tsx b/apps/nextjs-app/src/components/layouts/content-layout.tsx
index bd5a193b..78499a1c 100644
--- a/apps/nextjs-app/src/components/layouts/content-layout.tsx
+++ b/apps/nextjs-app/src/components/layouts/content-layout.tsx
@@ -2,10 +2,10 @@ import { ReactNode } from 'react';
type ContentLayoutProps = {
children: ReactNode;
- title: string;
+ title?: string;
};
-export const ContentLayout = ({ children, title }: ContentLayoutProps) => {
+export const ContentLayout = ({ children, title = '' }: ContentLayoutProps) => {
return (
diff --git a/apps/nextjs-app/src/features/comments/api/get-comments.ts b/apps/nextjs-app/src/features/comments/api/get-comments.ts
index c53c00fd..84c07ee5 100644
--- a/apps/nextjs-app/src/features/comments/api/get-comments.ts
+++ b/apps/nextjs-app/src/features/comments/api/get-comments.ts
@@ -7,29 +7,23 @@ import { Comment, Meta } from '@/types/api';
export const getComments = ({
discussionId,
page = 1,
- cookie,
}: {
discussionId: string;
page?: number;
- cookie?: string;
}): Promise<{ data: Comment[]; meta: Meta }> => {
return api.get(`/comments`, {
params: {
discussionId,
page,
},
- cookie,
});
};
-export const getInfiniteCommentsQueryOptions = (
- discussionId: string,
- cookie?: string,
-) => {
+export const getInfiniteCommentsQueryOptions = (discussionId: string) => {
return infiniteQueryOptions({
queryKey: ['comments', discussionId],
queryFn: ({ pageParam = 1 }) => {
- return getComments({ discussionId, page: pageParam as number, cookie });
+ return getComments({ discussionId, page: pageParam as number });
},
getNextPageParam: (lastPage) => {
if (lastPage?.meta?.page === lastPage?.meta?.totalPages) return undefined;
diff --git a/apps/nextjs-app/src/features/comments/components/comments-list.tsx b/apps/nextjs-app/src/features/comments/components/comments-list.tsx
index 0cde44d3..4b149662 100644
--- a/apps/nextjs-app/src/features/comments/components/comments-list.tsx
+++ b/apps/nextjs-app/src/features/comments/components/comments-list.tsx
@@ -7,8 +7,7 @@ import { Button } from '@/components/ui/button';
import { MDPreview } from '@/components/ui/md-preview';
import { Spinner } from '@/components/ui/spinner';
import { useUser } from '@/lib/auth';
-import { POLICIES, Authorization } from '@/lib/authorization';
-import { User } from '@/types/api';
+import { canDeleteComment } from '@/lib/authorization';
import { formatDate } from '@/utils/format';
import { useInfiniteComments } from '../api/get-comments';
@@ -68,15 +67,8 @@ export const CommentsList = ({ discussionId }: CommentsListProps) => {
)}
- {!isPublicView && (
-
-
-
+ {!isPublicView && canDeleteComment(user.data, comment) && (
+
)}
diff --git a/apps/nextjs-app/src/features/discussions/api/get-discussion.ts b/apps/nextjs-app/src/features/discussions/api/get-discussion.ts
index 63fb9195..592ef623 100644
--- a/apps/nextjs-app/src/features/discussions/api/get-discussion.ts
+++ b/apps/nextjs-app/src/features/discussions/api/get-discussion.ts
@@ -6,23 +6,16 @@ import { Discussion } from '@/types/api';
export const getDiscussion = ({
discussionId,
- cookie,
}: {
discussionId: string;
- cookie?: string;
}): Promise<{ data: Discussion }> => {
- return api.get(`/discussions/${discussionId}`, {
- cookie,
- });
+ return api.get(`/discussions/${discussionId}`);
};
-export const getDiscussionQueryOptions = (
- discussionId: string,
- cookie?: string,
-) => {
+export const getDiscussionQueryOptions = (discussionId: string) => {
return queryOptions({
queryKey: ['discussions', discussionId],
- queryFn: () => getDiscussion({ discussionId, cookie }),
+ queryFn: () => getDiscussion({ discussionId }),
});
};
diff --git a/apps/nextjs-app/src/features/discussions/api/get-discussions.ts b/apps/nextjs-app/src/features/discussions/api/get-discussions.ts
index f37dd4e3..10d75236 100644
--- a/apps/nextjs-app/src/features/discussions/api/get-discussions.ts
+++ b/apps/nextjs-app/src/features/discussions/api/get-discussions.ts
@@ -5,7 +5,7 @@ import { QueryConfig } from '@/lib/react-query';
import { Discussion, Meta } from '@/types/api';
export const getDiscussions = (
- { page, cookie }: { page?: number; cookie?: string } = { page: 1 },
+ { page }: { page?: number } = { page: 1 },
): Promise<{
data: Discussion[];
meta: Meta;
@@ -14,17 +14,15 @@ export const getDiscussions = (
params: {
page,
},
- cookie,
});
};
export const getDiscussionsQueryOptions = ({
- page,
- cookie,
-}: { page?: number; cookie?: string } = {}) => {
+ page = 1,
+}: { page?: number } = {}) => {
return queryOptions({
- queryKey: page ? ['discussions', { page }] : ['discussions'],
- queryFn: () => getDiscussions({ page, cookie }),
+ queryKey: ['discussions', { page }],
+ queryFn: () => getDiscussions({ page }),
});
};
diff --git a/apps/nextjs-app/src/features/discussions/components/create-discussion.tsx b/apps/nextjs-app/src/features/discussions/components/create-discussion.tsx
index cef8e56f..65fd245f 100644
--- a/apps/nextjs-app/src/features/discussions/components/create-discussion.tsx
+++ b/apps/nextjs-app/src/features/discussions/components/create-discussion.tsx
@@ -12,7 +12,8 @@ import {
Textarea,
} from '@/components/ui/form';
import { useNotifications } from '@/components/ui/notifications';
-import { Authorization, ROLES } from '@/lib/authorization';
+import { useUser } from '@/lib/auth';
+import { canCreateDiscussion } from '@/lib/authorization';
import {
createDiscussionInputSchema,
@@ -32,69 +33,73 @@ export const CreateDiscussion = () => {
},
});
+ const user = useUser();
+
+ if (!canCreateDiscussion(user?.data)) {
+ return null;
+ }
+
return (
-
- }>
- Create Discussion
-
- }
- title="Create Discussion"
- submitButton={
-
- Submit
-
- }
- >
-
-
-
+
+ setValue('public', value)}
+ checked={watch('public')}
+ className={` relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2`}
+ id="public"
+ />
+ Public
+
+ >
+ )}
+
+
);
};
diff --git a/apps/nextjs-app/src/features/discussions/components/delete-discussion.tsx b/apps/nextjs-app/src/features/discussions/components/delete-discussion.tsx
index d7709b23..5759aae1 100644
--- a/apps/nextjs-app/src/features/discussions/components/delete-discussion.tsx
+++ b/apps/nextjs-app/src/features/discussions/components/delete-discussion.tsx
@@ -5,7 +5,8 @@ import { Trash } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { ConfirmationDialog } from '@/components/ui/dialog';
import { useNotifications } from '@/components/ui/notifications';
-import { Authorization, ROLES } from '@/lib/authorization';
+import { useUser } from '@/lib/auth';
+import { canDeleteDiscussion } from '@/lib/authorization';
import { useDeleteDiscussion } from '../api/delete-discussion';
@@ -14,6 +15,7 @@ type DeleteDiscussionProps = {
};
export const DeleteDiscussion = ({ id }: DeleteDiscussionProps) => {
+ const user = useUser();
const { addNotification } = useNotifications();
const deleteDiscussionMutation = useDeleteDiscussion({
mutationConfig: {
@@ -26,30 +28,30 @@ export const DeleteDiscussion = ({ id }: DeleteDiscussionProps) => {
},
});
+ if (!canDeleteDiscussion(user?.data)) {
+ return null;
+ }
+
return (
-
- }>
- Delete Discussion
-
- }
- confirmButton={
-
- deleteDiscussionMutation.mutate({ discussionId: id })
- }
- >
- Delete Discussion
-
- }
- />
-
+ }>
+ Delete Discussion
+
+ }
+ confirmButton={
+ deleteDiscussionMutation.mutate({ discussionId: id })}
+ >
+ Delete Discussion
+
+ }
+ />
);
};
diff --git a/apps/nextjs-app/src/features/discussions/components/update-discussion.tsx b/apps/nextjs-app/src/features/discussions/components/update-discussion.tsx
index 11a9e8bb..d9f0fa21 100644
--- a/apps/nextjs-app/src/features/discussions/components/update-discussion.tsx
+++ b/apps/nextjs-app/src/features/discussions/components/update-discussion.tsx
@@ -12,7 +12,8 @@ import {
Textarea,
} from '@/components/ui/form';
import { useNotifications } from '@/components/ui/notifications';
-import { Authorization, ROLES } from '@/lib/authorization';
+import { useUser } from '@/lib/auth';
+import { canUpdateDiscussion } from '@/lib/authorization';
import { useDiscussion } from '../api/get-discussion';
import {
@@ -38,73 +39,77 @@ export const UpdateDiscussion = ({ discussionId }: UpdateDiscussionProps) => {
},
});
+ const user = useUser();
+
+ if (!canUpdateDiscussion(user?.data)) {
+ return null;
+ }
+
const discussion = discussionQuery.data?.data;
return (
-
- } size="sm">
- Update Discussion
-
- }
- title="Update Discussion"
- submitButton={
-
- Submit
-
- }
- >
- {
- updateDiscussionMutation.mutate({
- data: values,
- discussionId,
- });
- }}
- options={{
- defaultValues: {
- title: discussion?.title ?? '',
- body: discussion?.body ?? '',
- public: discussion?.public ?? false,
- },
- }}
- schema={updateDiscussionInputSchema}
+ } size="sm">
+ Update Discussion
+
+ }
+ title="Update Discussion"
+ submitButton={
+
- {({ register, formState, setValue, watch }) => (
- <>
-
-
+ Submit
+
+ }
+ >
+ {
+ updateDiscussionMutation.mutate({
+ data: values,
+ discussionId,
+ });
+ }}
+ options={{
+ defaultValues: {
+ title: discussion?.title ?? '',
+ body: discussion?.body ?? '',
+ public: discussion?.public ?? false,
+ },
+ }}
+ schema={updateDiscussionInputSchema}
+ >
+ {({ register, formState, setValue, watch }) => (
+ <>
+
+
-
- setValue('public', value)}
- checked={watch('public')}
- className={` relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2`}
- id="public"
- />
- Public
-
- >
- )}
-
-
-
+
+ setValue('public', value)}
+ checked={watch('public')}
+ className={` relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2`}
+ id="public"
+ />
+ Public
+
+ >
+ )}
+
+
);
};
diff --git a/apps/nextjs-app/src/lib/__tests__/authorization.test.tsx b/apps/nextjs-app/src/lib/__tests__/authorization.test.tsx
index 2580803b..973526d2 100644
--- a/apps/nextjs-app/src/lib/__tests__/authorization.test.tsx
+++ b/apps/nextjs-app/src/lib/__tests__/authorization.test.tsx
@@ -1,85 +1,103 @@
-import { createUser, renderApp, screen } from '@/testing/test-utils';
-
-import { Authorization, ROLES } from '../authorization';
-
-test('should view protected resource if user role is matching', async () => {
- const user = await createUser({
- role: ROLES.ADMIN,
+import { Comment, User } from '@/types/api';
+
+import {
+ canCreateDiscussion,
+ canDeleteDiscussion,
+ canUpdateDiscussion,
+ canViewUsers,
+ canDeleteComment,
+} from '../authorization';
+
+describe('Discussion Authorization', () => {
+ const adminUser: User = {
+ id: '1',
+ role: 'ADMIN',
+ } as User;
+
+ const regularUser: User = {
+ id: '2',
+ role: 'USER',
+ } as User;
+
+ test('should allow admin to create discussions', () => {
+ expect(canCreateDiscussion(adminUser)).toBe(true);
+ expect(canCreateDiscussion(regularUser)).toBe(false);
+ expect(canCreateDiscussion(null)).toBe(false);
+ expect(canCreateDiscussion(undefined)).toBe(false);
});
- const protectedResource = 'This is very confidential data';
-
- await renderApp(
-
- {protectedResource}
- ,
- {
- user,
- },
- );
-
- expect(screen.getByText(protectedResource)).toBeInTheDocument();
-});
-
-test('should not view protected resource if user role does not match and show fallback message instead', async () => {
- const user = await createUser({
- role: ROLES.USER,
+ test('should allow admin to delete discussions', () => {
+ expect(canDeleteDiscussion(adminUser)).toBe(true);
+ expect(canDeleteDiscussion(regularUser)).toBe(false);
+ expect(canDeleteDiscussion(null)).toBe(false);
+ expect(canDeleteDiscussion(undefined)).toBe(false);
});
- const protectedResource = 'This is very confidential data';
-
- const forbiddenMessage = 'You are unauthorized to view this resource';
- await renderApp(
- {forbiddenMessage}}
- allowedRoles={[ROLES.ADMIN]}
- >
- {protectedResource}
- ,
- { user },
- );
-
- await screen.findByText(forbiddenMessage);
-
- expect(screen.queryByText(protectedResource)).not.toBeInTheDocument();
+ test('should allow admin to update discussions', () => {
+ expect(canUpdateDiscussion(adminUser)).toBe(true);
+ expect(canUpdateDiscussion(regularUser)).toBe(false);
+ expect(canUpdateDiscussion(null)).toBe(false);
+ expect(canUpdateDiscussion(undefined)).toBe(false);
+ });
- expect(screen.getByText(forbiddenMessage)).toBeInTheDocument();
+ test('should allow admin to view users', () => {
+ expect(canViewUsers(adminUser)).toBe(true);
+ expect(canViewUsers(regularUser)).toBe(false);
+ expect(canViewUsers(null)).toBe(false);
+ expect(canViewUsers(undefined)).toBe(false);
+ });
});
-test('should view protected resource if policy check passes', async () => {
- const user = await createUser({
- role: ROLES.ADMIN,
+describe('Comment Authorization', () => {
+ const adminUser: User = {
+ id: '1',
+ role: 'ADMIN',
+ } as User;
+
+ const regularUser: User = {
+ id: '2',
+ role: 'USER',
+ } as User;
+
+ const anotherUser: User = {
+ id: '3',
+ role: 'USER',
+ } as User;
+
+ test('should allow admin to delete any comment', () => {
+ const comment: Comment = {
+ id: '1',
+ author: anotherUser,
+ } as Comment;
+
+ expect(canDeleteComment(adminUser, comment)).toBe(true);
});
- const protectedResource = 'This is very confidential data';
-
- await renderApp(
- {protectedResource} ,
- { user },
- );
+ test('should allow users to delete their own comments', () => {
+ const comment: Comment = {
+ id: '1',
+ author: regularUser,
+ } as Comment;
- expect(screen.getByText(protectedResource)).toBeInTheDocument();
-});
-
-test('should not view protected resource if policy check fails and show fallback message instead', async () => {
- const user = await createUser({
- role: ROLES.USER,
+ expect(canDeleteComment(regularUser, comment)).toBe(true);
});
- const protectedResource = 'This is very confidential data';
+ test('should not allow users to delete others comments', () => {
+ const comment: Comment = {
+ id: '1',
+ author: anotherUser,
+ } as Comment;
- const forbiddenMessage = 'You are unauthorized to view this resource';
- await renderApp(
- {forbiddenMessage}}
- policyCheck={false}
- >
- {protectedResource}
- ,
- { user },
- );
+ expect(canDeleteComment(regularUser, comment)).toBe(false);
+ });
- expect(screen.queryByText(protectedResource)).not.toBeInTheDocument();
+ test('should not allow unauthorized users to delete comments', () => {
+ const comment: Comment = {
+ id: '1',
+ author: regularUser,
+ } as Comment;
- expect(screen.getByText(forbiddenMessage)).toBeInTheDocument();
+ expect(canDeleteComment(null, comment)).toBe(false);
+ expect(canDeleteComment(undefined, comment)).toBe(false);
+ });
});
diff --git a/apps/nextjs-app/src/lib/api-client.ts b/apps/nextjs-app/src/lib/api-client.ts
index 797d2ad0..1b720ea3 100644
--- a/apps/nextjs-app/src/lib/api-client.ts
+++ b/apps/nextjs-app/src/lib/api-client.ts
@@ -28,6 +28,25 @@ function buildUrlWithParams(
return `${url}?${queryString}`;
}
+// Create a separate function for getting server-side cookies that can be imported where needed
+export function getServerCookies() {
+ if (typeof window !== 'undefined') return '';
+
+ // Dynamic import next/headers only on server-side
+ return import('next/headers').then(({ cookies }) => {
+ try {
+ const cookieStore = cookies();
+ return cookieStore
+ .getAll()
+ .map((c) => `${c.name}=${c.value}`)
+ .join('; ');
+ } catch (error) {
+ console.error('Failed to access cookies:', error);
+ return '';
+ }
+ });
+}
+
async function fetchApi(
url: string,
options: RequestOptions = {},
@@ -41,6 +60,13 @@ async function fetchApi(
cache = 'no-store',
next,
} = options;
+
+ // Get cookies from the request when running on server
+ let cookieHeader = cookie;
+ if (typeof window === 'undefined' && !cookie) {
+ cookieHeader = await getServerCookies();
+ }
+
const fullUrl = buildUrlWithParams(`${env.API_URL}${url}`, params);
const response = await fetch(fullUrl, {
@@ -49,7 +75,7 @@ async function fetchApi(
'Content-Type': 'application/json',
Accept: 'application/json',
...headers,
- ...(cookie ? { Cookie: cookie } : {}),
+ ...(cookieHeader ? { Cookie: cookieHeader } : {}),
},
body: body ? JSON.stringify(body) : undefined,
credentials: 'include',
diff --git a/apps/nextjs-app/src/lib/auth.tsx b/apps/nextjs-app/src/lib/auth.tsx
index ac798516..12ee8b11 100644
--- a/apps/nextjs-app/src/lib/auth.tsx
+++ b/apps/nextjs-app/src/lib/auth.tsx
@@ -1,11 +1,11 @@
-'use client';
-
-import { usePathname, useRouter } from 'next/navigation';
-import { useEffect } from 'react';
-import { configureAuth } from 'react-query-auth';
+import {
+ queryOptions,
+ useMutation,
+ useQuery,
+ useQueryClient,
+} from '@tanstack/react-query';
import { z } from 'zod';
-import { paths } from '@/config/paths';
import { AuthResponse, User } from '@/types/api';
import { api } from './api-client';
@@ -13,12 +13,56 @@ import { api } from './api-client';
// api call definitions for auth (types, schemas, requests):
// these are not part of features as this is a module shared across features
-const getUser = async (): Promise => {
+export const getUser = async (): Promise => {
const response = (await api.get('/auth/me')) as { data: User };
return response.data;
};
+const userQueryKey = ['user'];
+
+export const getUserQueryOptions = () => {
+ return queryOptions({
+ queryKey: userQueryKey,
+ queryFn: getUser,
+ });
+};
+
+export const useUser = () => useQuery(getUserQueryOptions());
+
+export const useLogin = ({ onSuccess }: { onSuccess?: () => void }) => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: loginWithEmailAndPassword,
+ onSuccess: (data) => {
+ queryClient.setQueryData(userQueryKey, data.user);
+ onSuccess?.();
+ },
+ });
+};
+
+export const useRegister = ({ onSuccess }: { onSuccess?: () => void }) => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: registerWithEmailAndPassword,
+ onSuccess: (data) => {
+ queryClient.setQueryData(userQueryKey, data.user);
+ onSuccess?.();
+ },
+ });
+};
+
+export const useLogout = ({ onSuccess }: { onSuccess?: () => void }) => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: logout,
+ onSuccess: () => {
+ queryClient.removeQueries({ queryKey: userQueryKey });
+ onSuccess?.();
+ },
+ });
+};
+
const logout = (): Promise => {
return api.post('/auth/logout');
};
@@ -61,33 +105,3 @@ const registerWithEmailAndPassword = (
): Promise => {
return api.post('/auth/register', data);
};
-
-const authConfig = {
- userFn: getUser,
- loginFn: async (data: LoginInput) => {
- const response = await loginWithEmailAndPassword(data);
- return response.user;
- },
- registerFn: async (data: RegisterInput) => {
- const response = await registerWithEmailAndPassword(data);
- return response.user;
- },
- logoutFn: logout,
-};
-
-export const { useUser, useLogin, useLogout, useRegister, AuthLoader } =
- configureAuth(authConfig);
-
-export const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
- const user = useUser();
- const router = useRouter();
- const pathname = usePathname();
-
- useEffect(() => {
- if (!user.data) {
- router.replace(paths.auth.login.getHref(pathname));
- }
- }, [user.data, router, pathname]);
-
- return children;
-};
diff --git a/apps/nextjs-app/src/lib/authorization.ts b/apps/nextjs-app/src/lib/authorization.ts
new file mode 100644
index 00000000..83d8df2c
--- /dev/null
+++ b/apps/nextjs-app/src/lib/authorization.ts
@@ -0,0 +1,30 @@
+import { Comment, User } from '@/types/api';
+
+export const canCreateDiscussion = (user: User | null | undefined) => {
+ return user?.role === 'ADMIN';
+};
+export const canDeleteDiscussion = (user: User | null | undefined) => {
+ return user?.role === 'ADMIN';
+};
+export const canUpdateDiscussion = (user: User | null | undefined) => {
+ return user?.role === 'ADMIN';
+};
+
+export const canViewUsers = (user: User | null | undefined) => {
+ return user?.role === 'ADMIN';
+};
+
+export const canDeleteComment = (
+ user: User | null | undefined,
+ comment: Comment,
+) => {
+ if (user?.role === 'ADMIN') {
+ return true;
+ }
+
+ if (user?.role === 'USER' && comment.author?.id === user.id) {
+ return true;
+ }
+
+ return false;
+};
diff --git a/apps/nextjs-app/src/lib/authorization.tsx b/apps/nextjs-app/src/lib/authorization.tsx
deleted file mode 100644
index 15625d80..00000000
--- a/apps/nextjs-app/src/lib/authorization.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-'use client';
-
-import { usePathname, useRouter } from 'next/navigation';
-import * as React from 'react';
-
-import { paths } from '@/config/paths';
-import { Comment, User } from '@/types/api';
-
-import { useUser } from './auth';
-
-export enum ROLES {
- ADMIN = 'ADMIN',
- USER = 'USER',
-}
-
-type RoleTypes = keyof typeof ROLES;
-
-export const POLICIES = {
- 'comment:delete': (user: User, comment: Comment) => {
- if (user?.role === 'ADMIN') {
- return true;
- }
-
- if (user?.role === 'USER' && comment.author?.id === user.id) {
- return true;
- }
-
- return false;
- },
-};
-
-export const useAuthorization = () => {
- const user = useUser();
- const router = useRouter();
- const pathname = usePathname();
-
- if (!user.data && !user.isLoading) {
- const redirectTo = encodeURIComponent(pathname);
- router.push(paths.auth.login.getHref(redirectTo));
- }
-
- const checkAccess = React.useCallback(
- ({ allowedRoles }: { allowedRoles: RoleTypes[] }) => {
- if (allowedRoles && allowedRoles.length > 0 && user.data) {
- return allowedRoles?.includes(user.data.role);
- }
-
- return true;
- },
- [user.data],
- );
-
- return { checkAccess, role: user?.data?.role };
-};
-
-type AuthorizationProps = {
- forbiddenFallback?: React.ReactNode;
- children: React.ReactNode;
-} & (
- | {
- allowedRoles: RoleTypes[];
- policyCheck?: never;
- }
- | {
- allowedRoles?: never;
- policyCheck: boolean;
- }
-);
-
-export const Authorization = ({
- policyCheck,
- allowedRoles,
- forbiddenFallback = null,
- children,
-}: AuthorizationProps) => {
- const { checkAccess } = useAuthorization();
-
- let canAccess = false;
-
- if (allowedRoles) {
- canAccess = checkAccess({ allowedRoles });
- }
-
- if (typeof policyCheck !== 'undefined') {
- canAccess = policyCheck;
- }
-
- return <>{canAccess ? children : forbiddenFallback}>;
-};
diff --git a/apps/nextjs-app/src/utils/auth.ts b/apps/nextjs-app/src/utils/auth.ts
index ee182bce..786f1585 100644
--- a/apps/nextjs-app/src/utils/auth.ts
+++ b/apps/nextjs-app/src/utils/auth.ts
@@ -3,6 +3,7 @@ import { cookies } from 'next/headers';
export const AUTH_TOKEN_COOKIE_NAME = 'bulletproof_react_app_token';
export const getAuthTokenCookie = () => {
+ if (typeof window !== 'undefined') return '';
const cookieStore = cookies();
return cookieStore.get(AUTH_TOKEN_COOKIE_NAME)?.value;
};
diff --git a/apps/nextjs-app/yarn.lock b/apps/nextjs-app/yarn.lock
index f7432784..2380b469 100644
--- a/apps/nextjs-app/yarn.lock
+++ b/apps/nextjs-app/yarn.lock
@@ -3437,23 +3437,48 @@
"@vitest/utils" "1.6.0"
chai "^4.3.10"
-"@vitest/runner@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.6.0.tgz#a6de49a96cb33b0e3ba0d9064a3e8d6ce2f08825"
- integrity sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==
+"@vitest/expect@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.4.tgz#48f4f53a01092a3bdc118cff245f79ef388bdd8e"
+ integrity sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==
dependencies:
- "@vitest/utils" "1.6.0"
- p-limit "^5.0.0"
- pathe "^1.1.1"
+ "@vitest/spy" "2.1.4"
+ "@vitest/utils" "2.1.4"
+ chai "^5.1.2"
+ tinyrainbow "^1.2.0"
-"@vitest/snapshot@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.6.0.tgz#deb7e4498a5299c1198136f56e6e0f692e6af470"
- integrity sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==
+"@vitest/mocker@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.4.tgz#0dc07edb9114f7f080a0181fbcdb16cd4a2d855d"
+ integrity sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==
dependencies:
- magic-string "^0.30.5"
- pathe "^1.1.1"
- pretty-format "^29.7.0"
+ "@vitest/spy" "2.1.4"
+ estree-walker "^3.0.3"
+ magic-string "^0.30.12"
+
+"@vitest/pretty-format@2.1.4", "@vitest/pretty-format@^2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.4.tgz#fc31993bdc1ef5a6c1a4aa6844e7ba55658a4f9f"
+ integrity sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==
+ dependencies:
+ tinyrainbow "^1.2.0"
+
+"@vitest/runner@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.4.tgz#f9346500bdd0be1c926daaac5d683bae87ceda2c"
+ integrity sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==
+ dependencies:
+ "@vitest/utils" "2.1.4"
+ pathe "^1.1.2"
+
+"@vitest/snapshot@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.4.tgz#ef8c3f605fbc23a32773256d37d3fdfd9b23d353"
+ integrity sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==
+ dependencies:
+ "@vitest/pretty-format" "2.1.4"
+ magic-string "^0.30.12"
+ pathe "^1.1.2"
"@vitest/spy@1.6.0":
version "1.6.0"
@@ -3462,6 +3487,13 @@
dependencies:
tinyspy "^2.2.0"
+"@vitest/spy@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.4.tgz#4e90f9783437c5841a27c80f8fd84d7289a6100a"
+ integrity sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==
+ dependencies:
+ tinyspy "^3.0.2"
+
"@vitest/utils@1.6.0", "@vitest/utils@^1.3.1":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.6.0.tgz#5c5675ca7d6f546a7b4337de9ae882e6c57896a1"
@@ -3472,6 +3504,15 @@
loupe "^2.3.7"
pretty-format "^29.7.0"
+"@vitest/utils@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.4.tgz#6d67ac966647a21ce8bc497472ce230de3b64537"
+ integrity sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==
+ dependencies:
+ "@vitest/pretty-format" "2.1.4"
+ loupe "^3.1.2"
+ tinyrainbow "^1.2.0"
+
"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb"
@@ -3662,7 +3703,7 @@ acorn-walk@^7.2.0:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn-walk@^8.0.2, acorn-walk@^8.3.2:
+acorn-walk@^8.0.2:
version "8.3.3"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e"
integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==
@@ -4001,6 +4042,11 @@ assertion-error@^1.1.0:
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+assertion-error@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7"
+ integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==
+
ast-types-flow@^0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6"
@@ -4400,6 +4446,17 @@ chai@^4.3.10:
pathval "^1.1.1"
type-detect "^4.1.0"
+chai@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d"
+ integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==
+ dependencies:
+ assertion-error "^2.0.1"
+ check-error "^2.1.1"
+ deep-eql "^5.0.1"
+ loupe "^3.1.0"
+ pathval "^2.0.0"
+
chalk@3.0.0, chalk@^3.0.0, chalk@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
@@ -4470,6 +4527,11 @@ check-error@^1.0.3:
dependencies:
get-func-name "^2.0.2"
+check-error@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc"
+ integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
+
chokidar@^3.5.3, chokidar@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
@@ -5079,6 +5141,13 @@ debug@^3.2.6, debug@^3.2.7:
dependencies:
ms "^2.1.1"
+debug@^4.3.7:
+ version "4.3.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
+ integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
+ dependencies:
+ ms "^2.1.3"
+
decimal.js@^10.4.2, decimal.js@^10.4.3:
version "10.4.3"
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23"
@@ -5096,6 +5165,11 @@ deep-eql@^4.1.3:
dependencies:
type-detect "^4.0.0"
+deep-eql@^5.0.1:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341"
+ integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
+
deep-equal@^2.0.5:
version "2.2.3"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1"
@@ -6104,6 +6178,11 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
dependencies:
homedir-polyfill "^1.0.1"
+expect-type@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75"
+ integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==
+
express@^4.18.2, express@^4.19.2:
version "4.19.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
@@ -7647,11 +7726,6 @@ js-git@^0.7.8:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-tokens@^9.0.0:
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.0.tgz#0f893996d6f3ed46df7f0a3b12a03f5fd84223c1"
- integrity sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==
-
js-yaml@^4.1.0, js-yaml@~4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
@@ -7948,14 +8022,6 @@ loader-utils@^3.2.1:
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5"
integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==
-local-pkg@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c"
- integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==
- dependencies:
- mlly "^1.4.2"
- pkg-types "^1.0.3"
-
locate-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
@@ -8056,6 +8122,11 @@ loupe@^2.3.6, loupe@^2.3.7:
dependencies:
get-func-name "^2.0.1"
+loupe@^3.1.0, loupe@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240"
+ integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==
+
lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
@@ -8097,6 +8168,13 @@ lz-string@^1.5.0:
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
+magic-string@^0.30.12:
+ version "0.30.12"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.12.tgz#9eb11c9d072b9bcb4940a5b2c2e1a217e4ee1a60"
+ integrity sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==
+ dependencies:
+ "@jridgewell/sourcemap-codec" "^1.5.0"
+
magic-string@^0.30.5:
version "0.30.11"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954"
@@ -8332,7 +8410,7 @@ mkdirp@^3.0.1:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
-mlly@^1.4.2, mlly@^1.7.1:
+mlly@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.1.tgz#e0336429bb0731b6a8e887b438cbdae522c8f32f"
integrity sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==
@@ -8357,7 +8435,7 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-ms@2.1.3, ms@^2.1.1:
+ms@2.1.3, ms@^2.1.1, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@@ -8830,13 +8908,6 @@ p-limit@^4.0.0:
dependencies:
yocto-queue "^1.0.0"
-p-limit@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-5.0.0.tgz#6946d5b7140b649b7a33a027d89b4c625b3a5985"
- integrity sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==
- dependencies:
- yocto-queue "^1.0.0"
-
p-locate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
@@ -9073,7 +9144,7 @@ path-type@^5.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8"
integrity sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==
-pathe@^1.1.1, pathe@^1.1.2:
+pathe@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
@@ -9083,6 +9154,11 @@ pathval@^1.1.1:
resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
+pathval@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25"
+ integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==
+
pbkdf2@^3.0.3, pbkdf2@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
@@ -9219,7 +9295,7 @@ pkg-dir@^7.0.0:
dependencies:
find-up "^6.3.0"
-pkg-types@^1.0.3, pkg-types@^1.1.1:
+pkg-types@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.3.tgz#161bb1242b21daf7795036803f28e30222e476e3"
integrity sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==
@@ -9762,11 +9838,6 @@ react-is@^18.0.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
-react-query-auth@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/react-query-auth/-/react-query-auth-2.3.0.tgz#2c03e4cd3c75a01bde0cfa97168b857906315449"
- integrity sha512-42IvqDxnQMOCdPmf+H8hMscO+1EgDPMuNnJrYEJwe8Itsd2z96obtlm85PvBk8BgvOQrKGEGx1VDsAIzk6y7yw==
-
react-refresh@^0.14.0, react-refresh@^0.14.2:
version "0.14.2"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9"
@@ -10618,10 +10689,10 @@ statuses@2.0.1, statuses@^2.0.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
-std-env@^3.5.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2"
- integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==
+std-env@^3.7.0:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5"
+ integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==
stdin-discarder@^0.2.1:
version "0.2.2"
@@ -10853,13 +10924,6 @@ strip-json-comments@^3.0.1, strip-json-comments@^3.1.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-strip-literal@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.0.tgz#6d82ade5e2e74f5c7e8739b6c84692bd65f0bd2a"
- integrity sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==
- dependencies:
- js-tokens "^9.0.0"
-
style-loader@^3.3.1:
version "3.3.4"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7"
@@ -11072,21 +11136,36 @@ tiny-invariant@^1.3.1, tiny-invariant@^1.3.3:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
-tinybench@^2.5.1:
+tinybench@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b"
integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==
-tinypool@^0.8.3:
- version "0.8.4"
- resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.4.tgz#e217fe1270d941b39e98c625dcecebb1408c9aa8"
- integrity sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==
+tinyexec@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.1.tgz#0ab0daf93b43e2c211212396bdb836b468c97c98"
+ integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==
+
+tinypool@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe"
+ integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==
+
+tinyrainbow@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5"
+ integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==
tinyspy@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.1.tgz#117b2342f1f38a0dbdcc73a50a454883adf861d1"
integrity sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==
+tinyspy@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a"
+ integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==
+
title-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982"
@@ -11573,15 +11652,14 @@ vary@^1, vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
-vite-node@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.6.0.tgz#2c7e61129bfecc759478fa592754fd9704aaba7f"
- integrity sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==
+vite-node@2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.4.tgz#97ffb6de913fd8d42253afe441f9512e9dbdfd5c"
+ integrity sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==
dependencies:
cac "^6.7.14"
- debug "^4.3.4"
- pathe "^1.1.1"
- picocolors "^1.0.0"
+ debug "^4.3.7"
+ pathe "^1.1.2"
vite "^5.0.0"
vite-tsconfig-paths@^4.3.2:
@@ -11604,31 +11682,31 @@ vite@^5.0.0:
optionalDependencies:
fsevents "~2.3.3"
-vitest@^1.5.2:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.6.0.tgz#9d5ad4752a3c451be919e412c597126cffb9892f"
- integrity sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==
- dependencies:
- "@vitest/expect" "1.6.0"
- "@vitest/runner" "1.6.0"
- "@vitest/snapshot" "1.6.0"
- "@vitest/spy" "1.6.0"
- "@vitest/utils" "1.6.0"
- acorn-walk "^8.3.2"
- chai "^4.3.10"
- debug "^4.3.4"
- execa "^8.0.1"
- local-pkg "^0.5.0"
- magic-string "^0.30.5"
- pathe "^1.1.1"
- picocolors "^1.0.0"
- std-env "^3.5.0"
- strip-literal "^2.0.0"
- tinybench "^2.5.1"
- tinypool "^0.8.3"
+vitest@^2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.4.tgz#ba8f4589fb639cf5a9e6af54781667312b3e8230"
+ integrity sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==
+ dependencies:
+ "@vitest/expect" "2.1.4"
+ "@vitest/mocker" "2.1.4"
+ "@vitest/pretty-format" "^2.1.4"
+ "@vitest/runner" "2.1.4"
+ "@vitest/snapshot" "2.1.4"
+ "@vitest/spy" "2.1.4"
+ "@vitest/utils" "2.1.4"
+ chai "^5.1.2"
+ debug "^4.3.7"
+ expect-type "^1.1.0"
+ magic-string "^0.30.12"
+ pathe "^1.1.2"
+ std-env "^3.7.0"
+ tinybench "^2.9.0"
+ tinyexec "^0.3.1"
+ tinypool "^1.0.1"
+ tinyrainbow "^1.2.0"
vite "^5.0.0"
- vite-node "1.6.0"
- why-is-node-running "^2.2.2"
+ vite-node "2.1.4"
+ why-is-node-running "^2.3.0"
vizion@~2.2.1:
version "2.2.1"
@@ -11848,7 +11926,7 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
-why-is-node-running@^2.2.2:
+why-is-node-running@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04"
integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==
diff --git a/apps/nextjs-pages/package.json b/apps/nextjs-pages/package.json
index f0e7f8c7..52620f92 100644
--- a/apps/nextjs-pages/package.json
+++ b/apps/nextjs-pages/package.json
@@ -111,7 +111,7 @@
"tsx": "^4.17.0",
"typescript": "^5.4.5",
"vite-tsconfig-paths": "^4.3.2",
- "vitest": "^1.5.2"
+ "vitest": "^2.1.4"
},
"msw": {
"workerDirectory": "public"
diff --git a/apps/nextjs-pages/yarn.lock b/apps/nextjs-pages/yarn.lock
index 8792d13e..205020cb 100644
--- a/apps/nextjs-pages/yarn.lock
+++ b/apps/nextjs-pages/yarn.lock
@@ -3437,23 +3437,48 @@
"@vitest/utils" "1.6.0"
chai "^4.3.10"
-"@vitest/runner@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.6.0.tgz#a6de49a96cb33b0e3ba0d9064a3e8d6ce2f08825"
- integrity sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==
+"@vitest/expect@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.4.tgz#48f4f53a01092a3bdc118cff245f79ef388bdd8e"
+ integrity sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==
dependencies:
- "@vitest/utils" "1.6.0"
- p-limit "^5.0.0"
- pathe "^1.1.1"
+ "@vitest/spy" "2.1.4"
+ "@vitest/utils" "2.1.4"
+ chai "^5.1.2"
+ tinyrainbow "^1.2.0"
-"@vitest/snapshot@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.6.0.tgz#deb7e4498a5299c1198136f56e6e0f692e6af470"
- integrity sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==
+"@vitest/mocker@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.4.tgz#0dc07edb9114f7f080a0181fbcdb16cd4a2d855d"
+ integrity sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==
dependencies:
- magic-string "^0.30.5"
- pathe "^1.1.1"
- pretty-format "^29.7.0"
+ "@vitest/spy" "2.1.4"
+ estree-walker "^3.0.3"
+ magic-string "^0.30.12"
+
+"@vitest/pretty-format@2.1.4", "@vitest/pretty-format@^2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.4.tgz#fc31993bdc1ef5a6c1a4aa6844e7ba55658a4f9f"
+ integrity sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==
+ dependencies:
+ tinyrainbow "^1.2.0"
+
+"@vitest/runner@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.4.tgz#f9346500bdd0be1c926daaac5d683bae87ceda2c"
+ integrity sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==
+ dependencies:
+ "@vitest/utils" "2.1.4"
+ pathe "^1.1.2"
+
+"@vitest/snapshot@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.4.tgz#ef8c3f605fbc23a32773256d37d3fdfd9b23d353"
+ integrity sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==
+ dependencies:
+ "@vitest/pretty-format" "2.1.4"
+ magic-string "^0.30.12"
+ pathe "^1.1.2"
"@vitest/spy@1.6.0":
version "1.6.0"
@@ -3462,6 +3487,13 @@
dependencies:
tinyspy "^2.2.0"
+"@vitest/spy@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.4.tgz#4e90f9783437c5841a27c80f8fd84d7289a6100a"
+ integrity sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==
+ dependencies:
+ tinyspy "^3.0.2"
+
"@vitest/utils@1.6.0", "@vitest/utils@^1.3.1":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.6.0.tgz#5c5675ca7d6f546a7b4337de9ae882e6c57896a1"
@@ -3472,6 +3504,15 @@
loupe "^2.3.7"
pretty-format "^29.7.0"
+"@vitest/utils@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.4.tgz#6d67ac966647a21ce8bc497472ce230de3b64537"
+ integrity sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==
+ dependencies:
+ "@vitest/pretty-format" "2.1.4"
+ loupe "^3.1.2"
+ tinyrainbow "^1.2.0"
+
"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb"
@@ -3662,7 +3703,7 @@ acorn-walk@^7.2.0:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn-walk@^8.0.2, acorn-walk@^8.3.2:
+acorn-walk@^8.0.2:
version "8.3.3"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e"
integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==
@@ -4001,6 +4042,11 @@ assertion-error@^1.1.0:
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+assertion-error@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7"
+ integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==
+
ast-types-flow@^0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6"
@@ -4409,6 +4455,17 @@ chai@^4.3.10:
pathval "^1.1.1"
type-detect "^4.1.0"
+chai@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d"
+ integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==
+ dependencies:
+ assertion-error "^2.0.1"
+ check-error "^2.1.1"
+ deep-eql "^5.0.1"
+ loupe "^3.1.0"
+ pathval "^2.0.0"
+
chalk@3.0.0, chalk@^3.0.0, chalk@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
@@ -4479,6 +4536,11 @@ check-error@^1.0.3:
dependencies:
get-func-name "^2.0.2"
+check-error@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc"
+ integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
+
chokidar@^3.5.3, chokidar@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
@@ -5088,6 +5150,13 @@ debug@^3.2.6, debug@^3.2.7:
dependencies:
ms "^2.1.1"
+debug@^4.3.7:
+ version "4.3.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
+ integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
+ dependencies:
+ ms "^2.1.3"
+
decimal.js@^10.4.2, decimal.js@^10.4.3:
version "10.4.3"
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23"
@@ -5105,6 +5174,11 @@ deep-eql@^4.1.3:
dependencies:
type-detect "^4.0.0"
+deep-eql@^5.0.1:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341"
+ integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
+
deep-equal@^2.0.5:
version "2.2.3"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1"
@@ -6113,6 +6187,11 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
dependencies:
homedir-polyfill "^1.0.1"
+expect-type@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75"
+ integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==
+
express@^4.18.2, express@^4.19.2:
version "4.19.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
@@ -7656,11 +7735,6 @@ js-git@^0.7.8:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-tokens@^9.0.0:
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.0.tgz#0f893996d6f3ed46df7f0a3b12a03f5fd84223c1"
- integrity sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==
-
js-yaml@^4.1.0, js-yaml@~4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
@@ -7957,14 +8031,6 @@ loader-utils@^3.2.1:
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5"
integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==
-local-pkg@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c"
- integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==
- dependencies:
- mlly "^1.4.2"
- pkg-types "^1.0.3"
-
locate-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
@@ -8065,6 +8131,11 @@ loupe@^2.3.6, loupe@^2.3.7:
dependencies:
get-func-name "^2.0.1"
+loupe@^3.1.0, loupe@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240"
+ integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==
+
lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
@@ -8106,6 +8177,13 @@ lz-string@^1.5.0:
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
+magic-string@^0.30.12:
+ version "0.30.12"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.12.tgz#9eb11c9d072b9bcb4940a5b2c2e1a217e4ee1a60"
+ integrity sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==
+ dependencies:
+ "@jridgewell/sourcemap-codec" "^1.5.0"
+
magic-string@^0.30.5:
version "0.30.11"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954"
@@ -8341,7 +8419,7 @@ mkdirp@^3.0.1:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
-mlly@^1.4.2, mlly@^1.7.1:
+mlly@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.1.tgz#e0336429bb0731b6a8e887b438cbdae522c8f32f"
integrity sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==
@@ -8366,7 +8444,7 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-ms@2.1.3, ms@^2.1.1:
+ms@2.1.3, ms@^2.1.1, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@@ -8844,13 +8922,6 @@ p-limit@^4.0.0:
dependencies:
yocto-queue "^1.0.0"
-p-limit@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-5.0.0.tgz#6946d5b7140b649b7a33a027d89b4c625b3a5985"
- integrity sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==
- dependencies:
- yocto-queue "^1.0.0"
-
p-locate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
@@ -9087,7 +9158,7 @@ path-type@^5.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8"
integrity sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==
-pathe@^1.1.1, pathe@^1.1.2:
+pathe@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
@@ -9097,6 +9168,11 @@ pathval@^1.1.1:
resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
+pathval@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25"
+ integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==
+
pbkdf2@^3.0.3, pbkdf2@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
@@ -9233,7 +9309,7 @@ pkg-dir@^7.0.0:
dependencies:
find-up "^6.3.0"
-pkg-types@^1.0.3, pkg-types@^1.1.1:
+pkg-types@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.3.tgz#161bb1242b21daf7795036803f28e30222e476e3"
integrity sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==
@@ -10632,10 +10708,10 @@ statuses@2.0.1, statuses@^2.0.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
-std-env@^3.5.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2"
- integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==
+std-env@^3.7.0:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5"
+ integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==
stdin-discarder@^0.2.1:
version "0.2.2"
@@ -10867,13 +10943,6 @@ strip-json-comments@^3.0.1, strip-json-comments@^3.1.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-strip-literal@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.0.tgz#6d82ade5e2e74f5c7e8739b6c84692bd65f0bd2a"
- integrity sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==
- dependencies:
- js-tokens "^9.0.0"
-
style-loader@^3.3.1:
version "3.3.4"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7"
@@ -11086,21 +11155,36 @@ tiny-invariant@^1.3.1, tiny-invariant@^1.3.3:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
-tinybench@^2.5.1:
+tinybench@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b"
integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==
-tinypool@^0.8.3:
- version "0.8.4"
- resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.4.tgz#e217fe1270d941b39e98c625dcecebb1408c9aa8"
- integrity sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==
+tinyexec@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.1.tgz#0ab0daf93b43e2c211212396bdb836b468c97c98"
+ integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==
+
+tinypool@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe"
+ integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==
+
+tinyrainbow@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5"
+ integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==
tinyspy@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.1.tgz#117b2342f1f38a0dbdcc73a50a454883adf861d1"
integrity sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==
+tinyspy@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a"
+ integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==
+
title-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982"
@@ -11587,15 +11671,14 @@ vary@^1, vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
-vite-node@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.6.0.tgz#2c7e61129bfecc759478fa592754fd9704aaba7f"
- integrity sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==
+vite-node@2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.4.tgz#97ffb6de913fd8d42253afe441f9512e9dbdfd5c"
+ integrity sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==
dependencies:
cac "^6.7.14"
- debug "^4.3.4"
- pathe "^1.1.1"
- picocolors "^1.0.0"
+ debug "^4.3.7"
+ pathe "^1.1.2"
vite "^5.0.0"
vite-tsconfig-paths@^4.3.2:
@@ -11618,31 +11701,31 @@ vite@^5.0.0:
optionalDependencies:
fsevents "~2.3.3"
-vitest@^1.5.2:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.6.0.tgz#9d5ad4752a3c451be919e412c597126cffb9892f"
- integrity sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==
- dependencies:
- "@vitest/expect" "1.6.0"
- "@vitest/runner" "1.6.0"
- "@vitest/snapshot" "1.6.0"
- "@vitest/spy" "1.6.0"
- "@vitest/utils" "1.6.0"
- acorn-walk "^8.3.2"
- chai "^4.3.10"
- debug "^4.3.4"
- execa "^8.0.1"
- local-pkg "^0.5.0"
- magic-string "^0.30.5"
- pathe "^1.1.1"
- picocolors "^1.0.0"
- std-env "^3.5.0"
- strip-literal "^2.0.0"
- tinybench "^2.5.1"
- tinypool "^0.8.3"
+vitest@^2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.4.tgz#ba8f4589fb639cf5a9e6af54781667312b3e8230"
+ integrity sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==
+ dependencies:
+ "@vitest/expect" "2.1.4"
+ "@vitest/mocker" "2.1.4"
+ "@vitest/pretty-format" "^2.1.4"
+ "@vitest/runner" "2.1.4"
+ "@vitest/snapshot" "2.1.4"
+ "@vitest/spy" "2.1.4"
+ "@vitest/utils" "2.1.4"
+ chai "^5.1.2"
+ debug "^4.3.7"
+ expect-type "^1.1.0"
+ magic-string "^0.30.12"
+ pathe "^1.1.2"
+ std-env "^3.7.0"
+ tinybench "^2.9.0"
+ tinyexec "^0.3.1"
+ tinypool "^1.0.1"
+ tinyrainbow "^1.2.0"
vite "^5.0.0"
- vite-node "1.6.0"
- why-is-node-running "^2.2.2"
+ vite-node "2.1.4"
+ why-is-node-running "^2.3.0"
vizion@~2.2.1:
version "2.2.1"
@@ -11862,7 +11945,7 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
-why-is-node-running@^2.2.2:
+why-is-node-running@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04"
integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==
diff --git a/apps/react-vite/package.json b/apps/react-vite/package.json
index 330abd0f..127b5073 100644
--- a/apps/react-vite/package.json
+++ b/apps/react-vite/package.json
@@ -109,7 +109,7 @@
"vite": "^5.2.10",
"vite-node": "^1.6.0",
"vite-tsconfig-paths": "^4.3.2",
- "vitest": "^1.5.2"
+ "vitest": "^2.1.4"
},
"msw": {
"workerDirectory": "public"
diff --git a/apps/react-vite/yarn.lock b/apps/react-vite/yarn.lock
index 9818d29d..bbf405ef 100644
--- a/apps/react-vite/yarn.lock
+++ b/apps/react-vite/yarn.lock
@@ -1428,6 +1428,11 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+"@jridgewell/sourcemap-codec@^1.5.0":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
+ integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
+
"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
version "0.3.25"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
@@ -3277,49 +3282,64 @@
"@types/babel__core" "^7.20.5"
react-refresh "^0.14.0"
-"@vitest/expect@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.6.0.tgz#0b3ba0914f738508464983f4d811bc122b51fb30"
- integrity sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==
+"@vitest/expect@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.4.tgz#48f4f53a01092a3bdc118cff245f79ef388bdd8e"
+ integrity sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==
dependencies:
- "@vitest/spy" "1.6.0"
- "@vitest/utils" "1.6.0"
- chai "^4.3.10"
+ "@vitest/spy" "2.1.4"
+ "@vitest/utils" "2.1.4"
+ chai "^5.1.2"
+ tinyrainbow "^1.2.0"
-"@vitest/runner@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.6.0.tgz#a6de49a96cb33b0e3ba0d9064a3e8d6ce2f08825"
- integrity sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==
+"@vitest/mocker@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.4.tgz#0dc07edb9114f7f080a0181fbcdb16cd4a2d855d"
+ integrity sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==
dependencies:
- "@vitest/utils" "1.6.0"
- p-limit "^5.0.0"
- pathe "^1.1.1"
+ "@vitest/spy" "2.1.4"
+ estree-walker "^3.0.3"
+ magic-string "^0.30.12"
-"@vitest/snapshot@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.6.0.tgz#deb7e4498a5299c1198136f56e6e0f692e6af470"
- integrity sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==
+"@vitest/pretty-format@2.1.4", "@vitest/pretty-format@^2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.4.tgz#fc31993bdc1ef5a6c1a4aa6844e7ba55658a4f9f"
+ integrity sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==
dependencies:
- magic-string "^0.30.5"
- pathe "^1.1.1"
- pretty-format "^29.7.0"
+ tinyrainbow "^1.2.0"
-"@vitest/spy@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.6.0.tgz#362cbd42ccdb03f1613798fde99799649516906d"
- integrity sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==
+"@vitest/runner@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.4.tgz#f9346500bdd0be1c926daaac5d683bae87ceda2c"
+ integrity sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==
dependencies:
- tinyspy "^2.2.0"
+ "@vitest/utils" "2.1.4"
+ pathe "^1.1.2"
-"@vitest/utils@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.6.0.tgz#5c5675ca7d6f546a7b4337de9ae882e6c57896a1"
- integrity sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==
+"@vitest/snapshot@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.4.tgz#ef8c3f605fbc23a32773256d37d3fdfd9b23d353"
+ integrity sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==
dependencies:
- diff-sequences "^29.6.3"
- estree-walker "^3.0.3"
- loupe "^2.3.7"
- pretty-format "^29.7.0"
+ "@vitest/pretty-format" "2.1.4"
+ magic-string "^0.30.12"
+ pathe "^1.1.2"
+
+"@vitest/spy@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.4.tgz#4e90f9783437c5841a27c80f8fd84d7289a6100a"
+ integrity sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==
+ dependencies:
+ tinyspy "^3.0.2"
+
+"@vitest/utils@2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.4.tgz#6d67ac966647a21ce8bc497472ce230de3b64537"
+ integrity sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==
+ dependencies:
+ "@vitest/pretty-format" "2.1.4"
+ loupe "^3.1.2"
+ tinyrainbow "^1.2.0"
"@yarnpkg/esbuild-plugin-pnp@^3.0.0-rc.10":
version "3.0.0-rc.15"
@@ -3382,7 +3402,7 @@ acorn-walk@^7.2.0:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn-walk@^8.0.2, acorn-walk@^8.3.2:
+acorn-walk@^8.0.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa"
integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==
@@ -3677,10 +3697,10 @@ assert@^2.1.0:
object.assign "^4.1.4"
util "^0.12.5"
-assertion-error@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
- integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+assertion-error@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7"
+ integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==
ast-types-flow@^0.0.8:
version "0.0.8"
@@ -3996,18 +4016,16 @@ capital-case@^1.0.4:
tslib "^2.0.3"
upper-case-first "^2.0.2"
-chai@^4.3.10:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1"
- integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==
+chai@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d"
+ integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==
dependencies:
- assertion-error "^1.1.0"
- check-error "^1.0.3"
- deep-eql "^4.1.3"
- get-func-name "^2.0.2"
- loupe "^2.3.6"
- pathval "^1.1.1"
- type-detect "^4.0.8"
+ assertion-error "^2.0.1"
+ check-error "^2.1.1"
+ deep-eql "^5.0.1"
+ loupe "^3.1.0"
+ pathval "^2.0.0"
chalk@3.0.0, chalk@^3.0.0, chalk@~3.0.0:
version "3.0.0"
@@ -4072,12 +4090,10 @@ charm@~0.1.1:
resolved "https://registry.yarnpkg.com/charm/-/charm-0.1.2.tgz#06c21eed1a1b06aeb67553cdc53e23274bac2296"
integrity sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==
-check-error@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694"
- integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==
- dependencies:
- get-func-name "^2.0.2"
+check-error@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc"
+ integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
chokidar@^3.5.3, chokidar@^3.6.0:
version "3.6.0"
@@ -4302,11 +4318,6 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
-confbox@^0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.7.tgz#ccfc0a2bcae36a84838e83a3b7f770fb17d6c579"
- integrity sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==
-
consola@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f"
@@ -4538,6 +4549,13 @@ debug@^3.2.6, debug@^3.2.7:
dependencies:
ms "^2.1.1"
+debug@^4.3.7:
+ version "4.3.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
+ integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
+ dependencies:
+ ms "^2.1.3"
+
debug@~4.3.1:
version "4.3.5"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
@@ -4550,12 +4568,10 @@ decimal.js@^10.4.2, decimal.js@^10.4.3:
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23"
integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
-deep-eql@^4.1.3:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d"
- integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==
- dependencies:
- type-detect "^4.0.0"
+deep-eql@^5.0.1:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341"
+ integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
deep-is@^0.1.3:
version "0.1.4"
@@ -4697,11 +4713,6 @@ didyoumean@^1.2.2:
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
-diff-sequences@^29.6.3:
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
- integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==
-
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -5429,6 +5440,11 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
dependencies:
homedir-polyfill "^1.0.1"
+expect-type@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75"
+ integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==
+
express@^4.17.3, express@^4.18.2, express@^4.19.2:
version "4.19.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
@@ -5819,11 +5835,6 @@ get-east-asian-width@^1.0.0:
resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e"
integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==
-get-func-name@^2.0.1, get-func-name@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
- integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
-
get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
@@ -6859,11 +6870,6 @@ js-git@^0.7.8:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-tokens@^9.0.0:
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.0.tgz#0f893996d6f3ed46df7f0a3b12a03f5fd84223c1"
- integrity sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==
-
js-yaml@^4.1.0, js-yaml@~4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
@@ -7145,14 +7151,6 @@ listr2@8.0.1:
rfdc "^1.3.0"
wrap-ansi "^9.0.0"
-local-pkg@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c"
- integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==
- dependencies:
- mlly "^1.4.2"
- pkg-types "^1.0.3"
-
locate-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
@@ -7239,12 +7237,10 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
-loupe@^2.3.6, loupe@^2.3.7:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697"
- integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==
- dependencies:
- get-func-name "^2.0.1"
+loupe@^3.1.0, loupe@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240"
+ integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==
lower-case@^2.0.2:
version "2.0.2"
@@ -7294,13 +7290,20 @@ magic-string@^0.27.0:
dependencies:
"@jridgewell/sourcemap-codec" "^1.4.13"
-magic-string@^0.30.0, magic-string@^0.30.5:
+magic-string@^0.30.0:
version "0.30.10"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e"
integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==
dependencies:
"@jridgewell/sourcemap-codec" "^1.4.15"
+magic-string@^0.30.12:
+ version "0.30.12"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.12.tgz#9eb11c9d072b9bcb4940a5b2c2e1a217e4ee1a60"
+ integrity sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==
+ dependencies:
+ "@jridgewell/sourcemap-codec" "^1.5.0"
+
make-dir@^2.0.0, make-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
@@ -7490,16 +7493,6 @@ mkdirp@^3.0.1:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
-mlly@^1.4.2, mlly@^1.6.1:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.0.tgz#587383ae40dda23cadb11c3c3cc972b277724271"
- integrity sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==
- dependencies:
- acorn "^8.11.3"
- pathe "^1.1.2"
- pkg-types "^1.1.0"
- ufo "^1.5.3"
-
module-details-from-path@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b"
@@ -7515,7 +7508,7 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-ms@2.1.3, ms@^2.1.1:
+ms@2.1.3, ms@^2.1.1, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@@ -7937,13 +7930,6 @@ p-limit@^3.0.2:
dependencies:
yocto-queue "^0.1.0"
-p-limit@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-5.0.0.tgz#6946d5b7140b649b7a33a027d89b4c625b3a5985"
- integrity sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==
- dependencies:
- yocto-queue "^1.0.0"
-
p-locate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
@@ -8148,10 +8134,10 @@ pathe@^1.1.1, pathe@^1.1.2:
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
-pathval@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
- integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
+pathval@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25"
+ integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==
peek-stream@^1.1.0:
version "1.1.3"
@@ -8287,15 +8273,6 @@ pkg-dir@^5.0.0:
dependencies:
find-up "^5.0.0"
-pkg-types@^1.0.3, pkg-types@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.0.tgz#3ec1bf33379030fd0a34c227b6c650e8ea7ca271"
- integrity sha512-/RpmvKdxKf8uILTtoOhAgf30wYbP2Qw+L9p3Rvshx1JZVX+XQNZQFjlbmGHEGIm4CkVPlSn+NXmIM8+9oWQaSA==
- dependencies:
- confbox "^0.1.7"
- mlly "^1.6.1"
- pathe "^1.1.2"
-
playwright-core@1.43.1:
version "1.43.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.43.1.tgz#0eafef9994c69c02a1a3825a4343e56c99c03b02"
@@ -9538,10 +9515,10 @@ statuses@2.0.1, statuses@^2.0.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
-std-env@^3.5.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2"
- integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==
+std-env@^3.7.0:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5"
+ integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==
stdin-discarder@^0.2.1:
version "0.2.2"
@@ -9710,13 +9687,6 @@ strip-json-comments@^3.0.1, strip-json-comments@^3.1.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-strip-literal@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.0.tgz#6d82ade5e2e74f5c7e8739b6c84692bd65f0bd2a"
- integrity sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==
- dependencies:
- js-tokens "^9.0.0"
-
sucrase@^3.32.0:
version "3.35.0"
resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263"
@@ -9914,20 +9884,30 @@ tiny-invariant@^1.3.1, tiny-invariant@^1.3.3:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
-tinybench@^2.5.1:
- version "2.8.0"
- resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.8.0.tgz#30e19ae3a27508ee18273ffed9ac7018949acd7b"
- integrity sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==
+tinybench@^2.9.0:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b"
+ integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==
-tinypool@^0.8.3:
- version "0.8.4"
- resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.4.tgz#e217fe1270d941b39e98c625dcecebb1408c9aa8"
- integrity sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==
+tinyexec@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.1.tgz#0ab0daf93b43e2c211212396bdb836b468c97c98"
+ integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==
-tinyspy@^2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.1.tgz#117b2342f1f38a0dbdcc73a50a454883adf861d1"
- integrity sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==
+tinypool@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe"
+ integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==
+
+tinyrainbow@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5"
+ integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==
+
+tinyspy@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a"
+ integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==
title-case@^3.0.3:
version "3.0.3"
@@ -10074,7 +10054,7 @@ type-check@^0.4.0, type-check@~0.4.0:
dependencies:
prelude-ls "^1.2.1"
-type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.8:
+type-detect@4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
@@ -10171,7 +10151,7 @@ typescript@^5.4.5:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
-ufo@^1.4.0, ufo@^1.5.3:
+ufo@^1.4.0:
version "1.5.3"
resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.3.tgz#3325bd3c977b6c6cd3160bf4ff52989adc9d3344"
integrity sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==
@@ -10391,7 +10371,17 @@ vary@^1, vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
-vite-node@1.6.0, vite-node@^1.6.0:
+vite-node@2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.4.tgz#97ffb6de913fd8d42253afe441f9512e9dbdfd5c"
+ integrity sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==
+ dependencies:
+ cac "^6.7.14"
+ debug "^4.3.7"
+ pathe "^1.1.2"
+ vite "^5.0.0"
+
+vite-node@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.6.0.tgz#2c7e61129bfecc759478fa592754fd9704aaba7f"
integrity sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==
@@ -10422,31 +10412,31 @@ vite@^5.0.0, vite@^5.2.10:
optionalDependencies:
fsevents "~2.3.3"
-vitest@^1.5.2:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.6.0.tgz#9d5ad4752a3c451be919e412c597126cffb9892f"
- integrity sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==
- dependencies:
- "@vitest/expect" "1.6.0"
- "@vitest/runner" "1.6.0"
- "@vitest/snapshot" "1.6.0"
- "@vitest/spy" "1.6.0"
- "@vitest/utils" "1.6.0"
- acorn-walk "^8.3.2"
- chai "^4.3.10"
- debug "^4.3.4"
- execa "^8.0.1"
- local-pkg "^0.5.0"
- magic-string "^0.30.5"
- pathe "^1.1.1"
- picocolors "^1.0.0"
- std-env "^3.5.0"
- strip-literal "^2.0.0"
- tinybench "^2.5.1"
- tinypool "^0.8.3"
+vitest@^2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.4.tgz#ba8f4589fb639cf5a9e6af54781667312b3e8230"
+ integrity sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==
+ dependencies:
+ "@vitest/expect" "2.1.4"
+ "@vitest/mocker" "2.1.4"
+ "@vitest/pretty-format" "^2.1.4"
+ "@vitest/runner" "2.1.4"
+ "@vitest/snapshot" "2.1.4"
+ "@vitest/spy" "2.1.4"
+ "@vitest/utils" "2.1.4"
+ chai "^5.1.2"
+ debug "^4.3.7"
+ expect-type "^1.1.0"
+ magic-string "^0.30.12"
+ pathe "^1.1.2"
+ std-env "^3.7.0"
+ tinybench "^2.9.0"
+ tinyexec "^0.3.1"
+ tinypool "^1.0.1"
+ tinyrainbow "^1.2.0"
vite "^5.0.0"
- vite-node "1.6.0"
- why-is-node-running "^2.2.2"
+ vite-node "2.1.4"
+ why-is-node-running "^2.3.0"
vizion@~2.2.1:
version "2.2.1"
@@ -10619,10 +10609,10 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
-why-is-node-running@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.2.2.tgz#4185b2b4699117819e7154594271e7e344c9973e"
- integrity sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==
+why-is-node-running@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04"
+ integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==
dependencies:
siginfo "^2.0.0"
stackback "0.0.2"
@@ -10770,11 +10760,6 @@ yocto-queue@^0.1.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
-yocto-queue@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
- integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
-
zod@^3.23.4:
version "3.23.6"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.6.tgz#c08a977e2255dab1fdba933651584a05fcbf19e1"