chore:lint

This commit is contained in:
Bereket Engida
2024-10-30 09:20:44 +03:00
parent 5d1a6772e8
commit 5e0edd35c2
21 changed files with 872 additions and 772 deletions

View File

@@ -267,32 +267,129 @@ export const Icons = {
height="1.2em" height="1.2em"
viewBox="0 0 100 100" viewBox="0 0 100 100"
> >
<mask id="a" style={{maskType: "alpha"}} maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100"> <mask
<circle cx="50" cy="50" r="50" className="fill-foreground"/> id="a"
style={{ maskType: "alpha" }}
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="100"
height="100"
>
<circle cx="50" cy="50" r="50" className="fill-foreground" />
</mask> </mask>
<g mask="url(#a)"> <g mask="url(#a)">
<circle cx="11" cy="119" r="52" className="fill-muted-foreground stroke-foreground" strokeWidth="4"/> <circle
<circle cx="10" cy="125" r="52" className="fill-muted-foreground stroke-foreground" strokeWidth="4"/> cx="11"
<circle cx="9" cy="131" r="52" className="fill-muted-foreground stroke-muted-foreground" strokeWidth="4"/> cy="119"
<circle cx="88" cy="119" r="52" className="fill-muted-foreground stroke-foreground" strokeWidth="4"/> r="52"
<path className="fill-foreground" d="M89 35h2v5h-2zM83 34l2 1-1 4h-2zM77 31l2 1-3 4-2-1zM73 27l1 1-3 4-1-2zM70 23l1 1-4 3-1-2zM68 18v2l-4 1-1-2zM68 11l1 2-5 1-1-2zM69 6v2h-5V6z"/> className="fill-muted-foreground stroke-foreground"
<circle cx="89" cy="125" r="52" className="fill-muted-foreground stroke-foreground" strokeWidth="4"/> strokeWidth="4"
<circle cx="90" cy="131" r="52" className="fill-muted-foreground stroke-muted-foreground" strokeWidth="4"/> />
<ellipse cx="49.5" cy="119" rx="41.5" ry="51" className="fill-muted-foreground"/> <circle
<path d="M34 38v-9c1 1 2 4 5 6l7 30-8 2c-1-23-2-23-4-29Z" className="fill-foreground stroke-muted-foreground"/> cx="10"
<path fillRule="evenodd" clipRule="evenodd" d="M95 123c0 31-20 57-45 57S5 154 5 123c0-27 14-50 33-56l12-2c25 0 45 26 45 58Zm-45 47c22 0 39-22 39-50S72 70 50 70s-39 22-39 50 17 50 39 50Z" className="fill-foreground"/> cy="125"
<path d="M34 29c-4-8-11-5-14-4 2 3 5 4 9 4h5Z" className="fill-foreground stroke-muted-foreground"/> r="52"
<path d="M25 38c-1 6 0 14 2 18 5-7 7-13 7-18v-9c-5 1-7 5-9 9Z" className="fill-muted-foreground"/> className="fill-muted-foreground stroke-foreground"
<path d="M34 29c-1 3-5 11-5 16m5-16c-5 1-7 5-9 9-1 6 0 14 2 18 5-7 7-13 7-18v-9Z" className="stroke-muted-foreground"/> strokeWidth="4"
<path d="M44 18c-10 1-11 7-10 11l4-3c5-4 6-7 6-8Z" className="fill-foreground stroke-muted-foreground"/> />
<path d="M34 29h7l18 4c-3-6-9-14-21-7l-4 3Z" className="fill-foreground"/> <circle
<path d="M34 29c4-2 12-5 18-1m-18 1h7l18 4c-3-6-9-14-21-7l-4 3Z" className="stroke-muted-foreground"/> cx="9"
<path d="M32 29a1189 1189 0 0 1-16 19c0-17 7-18 13-19h5a14 14 0 0 1-2 0Z" className="fill-foreground"/> cy="131"
<path d="M34 29c-5 1-7 5-9 9l-9 10c0-17 7-18 13-19h5Zm0 0c-5 2-11 3-14 10" className="stroke-muted-foreground"/> r="52"
<path d="M41 29c9 2 13 10 15 14a25 25 0 0 1-22-14h7Z" className="fill-foreground"/> className="fill-muted-foreground stroke-muted-foreground"
<path d="M34 29c3 1 11 5 15 9m-15-9h7c9 2 13 10 15 14a25 25 0 0 1-22-14Z" className="stroke-muted-foreground"/> strokeWidth="4"
<circle cx="91.5" cy="12.5" r="18.5" className="fill-foreground stroke-muted-foreground" strokeWidth="2"/> />
<circle
cx="88"
cy="119"
r="52"
className="fill-muted-foreground stroke-foreground"
strokeWidth="4"
/>
<path
className="fill-foreground"
d="M89 35h2v5h-2zM83 34l2 1-1 4h-2zM77 31l2 1-3 4-2-1zM73 27l1 1-3 4-1-2zM70 23l1 1-4 3-1-2zM68 18v2l-4 1-1-2zM68 11l1 2-5 1-1-2zM69 6v2h-5V6z"
/>
<circle
cx="89"
cy="125"
r="52"
className="fill-muted-foreground stroke-foreground"
strokeWidth="4"
/>
<circle
cx="90"
cy="131"
r="52"
className="fill-muted-foreground stroke-muted-foreground"
strokeWidth="4"
/>
<ellipse
cx="49.5"
cy="119"
rx="41.5"
ry="51"
className="fill-muted-foreground"
/>
<path
d="M34 38v-9c1 1 2 4 5 6l7 30-8 2c-1-23-2-23-4-29Z"
className="fill-foreground stroke-muted-foreground"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M95 123c0 31-20 57-45 57S5 154 5 123c0-27 14-50 33-56l12-2c25 0 45 26 45 58Zm-45 47c22 0 39-22 39-50S72 70 50 70s-39 22-39 50 17 50 39 50Z"
className="fill-foreground"
/>
<path
d="M34 29c-4-8-11-5-14-4 2 3 5 4 9 4h5Z"
className="fill-foreground stroke-muted-foreground"
/>
<path
d="M25 38c-1 6 0 14 2 18 5-7 7-13 7-18v-9c-5 1-7 5-9 9Z"
className="fill-muted-foreground"
/>
<path
d="M34 29c-1 3-5 11-5 16m5-16c-5 1-7 5-9 9-1 6 0 14 2 18 5-7 7-13 7-18v-9Z"
className="stroke-muted-foreground"
/>
<path
d="M44 18c-10 1-11 7-10 11l4-3c5-4 6-7 6-8Z"
className="fill-foreground stroke-muted-foreground"
/>
<path
d="M34 29h7l18 4c-3-6-9-14-21-7l-4 3Z"
className="fill-foreground"
/>
<path
d="M34 29c4-2 12-5 18-1m-18 1h7l18 4c-3-6-9-14-21-7l-4 3Z"
className="stroke-muted-foreground"
/>
<path
d="M32 29a1189 1189 0 0 1-16 19c0-17 7-18 13-19h5a14 14 0 0 1-2 0Z"
className="fill-foreground"
/>
<path
d="M34 29c-5 1-7 5-9 9l-9 10c0-17 7-18 13-19h5Zm0 0c-5 2-11 3-14 10"
className="stroke-muted-foreground"
/>
<path
d="M41 29c9 2 13 10 15 14a25 25 0 0 1-22-14h7Z"
className="fill-foreground"
/>
<path
d="M34 29c3 1 11 5 15 9m-15-9h7c9 2 13 10 15 14a25 25 0 0 1-22-14Z"
className="stroke-muted-foreground"
/>
<circle
cx="91.5"
cy="12.5"
r="18.5"
className="fill-foreground stroke-muted-foreground"
strokeWidth="2"
/>
</g> </g>
</svg> </svg>
) ),
}; };

View File

@@ -37,5 +37,5 @@ export const techStackIcons: TechStackIconType = {
tanstack: { tanstack: {
name: "TanStack Start", name: "TanStack Start",
icon: <Icons.tanstack className="w-10 h-10" />, icon: <Icons.tanstack className="w-10 h-10" />,
} },
}; };

View File

@@ -1,9 +1,9 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as AvatarPrimitive from "@radix-ui/react-avatar" import * as AvatarPrimitive from "@radix-ui/react-avatar";
import { cn } from "~/lib/utils" import { cn } from "~/lib/utils";
const Avatar = React.forwardRef< const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>, React.ElementRef<typeof AvatarPrimitive.Root>,
@@ -13,12 +13,12 @@ const Avatar = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className className,
)} )}
{...props} {...props}
/> />
)) ));
Avatar.displayName = AvatarPrimitive.Root.displayName Avatar.displayName = AvatarPrimitive.Root.displayName;
const AvatarImage = React.forwardRef< const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>, React.ElementRef<typeof AvatarPrimitive.Image>,
@@ -29,8 +29,8 @@ const AvatarImage = React.forwardRef<
className={cn("aspect-square h-full w-full", className)} className={cn("aspect-square h-full w-full", className)}
{...props} {...props}
/> />
)) ));
AvatarImage.displayName = AvatarPrimitive.Image.displayName AvatarImage.displayName = AvatarPrimitive.Image.displayName;
const AvatarFallback = React.forwardRef< const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>, React.ElementRef<typeof AvatarPrimitive.Fallback>,
@@ -40,11 +40,11 @@ const AvatarFallback = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted", "flex h-full w-full items-center justify-center rounded-full bg-muted",
className className,
)} )}
{...props} {...props}
/> />
)) ));
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
export { Avatar, AvatarImage, AvatarFallback } export { Avatar, AvatarImage, AvatarFallback };

View File

@@ -1,18 +1,18 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog" import * as DialogPrimitive from "@radix-ui/react-dialog";
import { X } from "lucide-react" import { X } from "lucide-react";
import { cn } from "~/lib/utils" import { cn } from "~/lib/utils";
const Dialog = DialogPrimitive.Root const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger const DialogTrigger = DialogPrimitive.Trigger;
const DialogPortal = DialogPrimitive.Portal const DialogPortal = DialogPrimitive.Portal;
const DialogClose = DialogPrimitive.Close const DialogClose = DialogPrimitive.Close;
const DialogOverlay = React.forwardRef< const DialogOverlay = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Overlay>, React.ElementRef<typeof DialogPrimitive.Overlay>,
@@ -22,12 +22,12 @@ const DialogOverlay = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className className,
)} )}
{...props} {...props}
/> />
)) ));
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
const DialogContent = React.forwardRef< const DialogContent = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>, React.ElementRef<typeof DialogPrimitive.Content>,
@@ -39,7 +39,7 @@ const DialogContent = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
className className,
)} )}
{...props} {...props}
> >
@@ -50,8 +50,8 @@ const DialogContent = React.forwardRef<
</DialogPrimitive.Close> </DialogPrimitive.Close>
</DialogPrimitive.Content> </DialogPrimitive.Content>
</DialogPortal> </DialogPortal>
)) ));
DialogContent.displayName = DialogPrimitive.Content.displayName DialogContent.displayName = DialogPrimitive.Content.displayName;
const DialogHeader = ({ const DialogHeader = ({
className, className,
@@ -60,12 +60,12 @@ const DialogHeader = ({
<div <div
className={cn( className={cn(
"flex flex-col space-y-1.5 text-center sm:text-left", "flex flex-col space-y-1.5 text-center sm:text-left",
className className,
)} )}
{...props} {...props}
/> />
) );
DialogHeader.displayName = "DialogHeader" DialogHeader.displayName = "DialogHeader";
const DialogFooter = ({ const DialogFooter = ({
className, className,
@@ -74,12 +74,12 @@ const DialogFooter = ({
<div <div
className={cn( className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className className,
)} )}
{...props} {...props}
/> />
) );
DialogFooter.displayName = "DialogFooter" DialogFooter.displayName = "DialogFooter";
const DialogTitle = React.forwardRef< const DialogTitle = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Title>, React.ElementRef<typeof DialogPrimitive.Title>,
@@ -89,12 +89,12 @@ const DialogTitle = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
"text-lg font-semibold leading-none tracking-tight", "text-lg font-semibold leading-none tracking-tight",
className className,
)} )}
{...props} {...props}
/> />
)) ));
DialogTitle.displayName = DialogPrimitive.Title.displayName DialogTitle.displayName = DialogPrimitive.Title.displayName;
const DialogDescription = React.forwardRef< const DialogDescription = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Description>, React.ElementRef<typeof DialogPrimitive.Description>,
@@ -105,8 +105,8 @@ const DialogDescription = React.forwardRef<
className={cn("text-sm text-muted-foreground", className)} className={cn("text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)) ));
DialogDescription.displayName = DialogPrimitive.Description.displayName DialogDescription.displayName = DialogPrimitive.Description.displayName;
export { export {
Dialog, Dialog,
@@ -119,4 +119,4 @@ export {
DialogFooter, DialogFooter,
DialogTitle, DialogTitle,
DialogDescription, DialogDescription,
} };

View File

@@ -1,14 +1,14 @@
"use client" "use client";
import * as React from "react" import * as React from "react";
import * as LabelPrimitive from "@radix-ui/react-label" import * as LabelPrimitive from "@radix-ui/react-label";
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "~/lib/utils" import { cn } from "~/lib/utils";
const labelVariants = cva( const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
) );
const Label = React.forwardRef< const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>, React.ElementRef<typeof LabelPrimitive.Root>,
@@ -20,7 +20,7 @@ const Label = React.forwardRef<
className={cn(labelVariants(), className)} className={cn(labelVariants(), className)}
{...props} {...props}
/> />
)) ));
Label.displayName = LabelPrimitive.Root.displayName Label.displayName = LabelPrimitive.Root.displayName;
export { Label } export { Label };

View File

@@ -1,9 +1,12 @@
import { twoFactorClient } from "better-auth/plugins"; import { twoFactorClient } from "better-auth/plugins";
import { createAuthClient } from "better-auth/react"; import { createAuthClient } from "better-auth/react";
export const { useSession, signIn, signOut, signUp, twoFactor } = createAuthClient({ export const { useSession, signIn, signOut, signUp, twoFactor } =
createAuthClient({
baseURL: "http://localhost:3000", baseURL: "http://localhost:3000",
plugins: [twoFactorClient({ plugins: [
twoFactorClient({
twoFactorPage: "/auth/two-factor", twoFactorPage: "/auth/two-factor",
})] }),
}); ],
});

View File

@@ -1,4 +1,4 @@
import { twoFactor } from 'better-auth/plugins'; import { twoFactor } from "better-auth/plugins";
import { betterAuth } from "better-auth"; import { betterAuth } from "better-auth";
import Database from "better-sqlite3"; import Database from "better-sqlite3";
@@ -19,5 +19,5 @@ export const auth = betterAuth({
clientSecret: process.env.GITHUB_CLIENT_SECRET!, clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}, },
}, },
plugins: [twoFactor()] plugins: [twoFactor()],
}); });

View File

@@ -1,4 +1,4 @@
import { X } from 'lucide-react-native'; import { X } from "lucide-react-native";
import { iconWithClassName } from './iconWithClassName'; import { iconWithClassName } from "./iconWithClassName";
iconWithClassName(X); iconWithClassName(X);
export { X }; export { X };

View File

@@ -1,14 +1,14 @@
import type { LucideIcon } from 'lucide-react-native'; import type { LucideIcon } from "lucide-react-native";
import { cssInterop } from 'nativewind'; import { cssInterop } from "nativewind";
export function iconWithClassName(icon: LucideIcon) { export function iconWithClassName(icon: LucideIcon) {
cssInterop(icon, { cssInterop(icon, {
className: { className: {
target: 'style', target: "style",
nativeStyleToProp: { nativeStyleToProp: {
color: true, color: true,
opacity: true, opacity: true,
}, },
}, },
}); });
} }

View File

@@ -1,9 +1,9 @@
import { LoginForm } from "~/components/login-form" import { LoginForm } from "~/components/login-form";
export default function Page() { export default function Page() {
return ( return (
<div className="flex h-screen w-full items-center justify-center px-4"> <div className="flex h-screen w-full items-center justify-center px-4">
<LoginForm /> <LoginForm />
</div> </div>
) );
} }

View File

@@ -10,111 +10,111 @@
// Import Routes // Import Routes
import { Route as rootRoute } from './routes/__root' import { Route as rootRoute } from "./routes/__root";
import { Route as IndexImport } from './routes/index' import { Route as IndexImport } from "./routes/index";
import { Route as AuthTwoFactorImport } from './routes/auth/two-factor' import { Route as AuthTwoFactorImport } from "./routes/auth/two-factor";
import { Route as AuthSignupImport } from './routes/auth/signup' import { Route as AuthSignupImport } from "./routes/auth/signup";
import { Route as AuthSigninImport } from './routes/auth/signin' import { Route as AuthSigninImport } from "./routes/auth/signin";
// Create/Update Routes // Create/Update Routes
const IndexRoute = IndexImport.update({ const IndexRoute = IndexImport.update({
id: '/', id: "/",
path: '/', path: "/",
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
} as any) } as any);
const AuthTwoFactorRoute = AuthTwoFactorImport.update({ const AuthTwoFactorRoute = AuthTwoFactorImport.update({
id: '/auth/two-factor', id: "/auth/two-factor",
path: '/auth/two-factor', path: "/auth/two-factor",
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
} as any) } as any);
const AuthSignupRoute = AuthSignupImport.update({ const AuthSignupRoute = AuthSignupImport.update({
id: '/auth/signup', id: "/auth/signup",
path: '/auth/signup', path: "/auth/signup",
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
} as any) } as any);
const AuthSigninRoute = AuthSigninImport.update({ const AuthSigninRoute = AuthSigninImport.update({
id: '/auth/signin', id: "/auth/signin",
path: '/auth/signin', path: "/auth/signin",
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
} as any) } as any);
// Populate the FileRoutesByPath interface // Populate the FileRoutesByPath interface
declare module '@tanstack/react-router' { declare module "@tanstack/react-router" {
interface FileRoutesByPath { interface FileRoutesByPath {
'/': { "/": {
id: '/' id: "/";
path: '/' path: "/";
fullPath: '/' fullPath: "/";
preLoaderRoute: typeof IndexImport preLoaderRoute: typeof IndexImport;
parentRoute: typeof rootRoute parentRoute: typeof rootRoute;
} };
'/auth/signin': { "/auth/signin": {
id: '/auth/signin' id: "/auth/signin";
path: '/auth/signin' path: "/auth/signin";
fullPath: '/auth/signin' fullPath: "/auth/signin";
preLoaderRoute: typeof AuthSigninImport preLoaderRoute: typeof AuthSigninImport;
parentRoute: typeof rootRoute parentRoute: typeof rootRoute;
} };
'/auth/signup': { "/auth/signup": {
id: '/auth/signup' id: "/auth/signup";
path: '/auth/signup' path: "/auth/signup";
fullPath: '/auth/signup' fullPath: "/auth/signup";
preLoaderRoute: typeof AuthSignupImport preLoaderRoute: typeof AuthSignupImport;
parentRoute: typeof rootRoute parentRoute: typeof rootRoute;
} };
'/auth/two-factor': { "/auth/two-factor": {
id: '/auth/two-factor' id: "/auth/two-factor";
path: '/auth/two-factor' path: "/auth/two-factor";
fullPath: '/auth/two-factor' fullPath: "/auth/two-factor";
preLoaderRoute: typeof AuthTwoFactorImport preLoaderRoute: typeof AuthTwoFactorImport;
parentRoute: typeof rootRoute parentRoute: typeof rootRoute;
} };
} }
} }
// Create and export the route tree // Create and export the route tree
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof IndexRoute "/": typeof IndexRoute;
'/auth/signin': typeof AuthSigninRoute "/auth/signin": typeof AuthSigninRoute;
'/auth/signup': typeof AuthSignupRoute "/auth/signup": typeof AuthSignupRoute;
'/auth/two-factor': typeof AuthTwoFactorRoute "/auth/two-factor": typeof AuthTwoFactorRoute;
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/': typeof IndexRoute "/": typeof IndexRoute;
'/auth/signin': typeof AuthSigninRoute "/auth/signin": typeof AuthSigninRoute;
'/auth/signup': typeof AuthSignupRoute "/auth/signup": typeof AuthSignupRoute;
'/auth/two-factor': typeof AuthTwoFactorRoute "/auth/two-factor": typeof AuthTwoFactorRoute;
} }
export interface FileRoutesById { export interface FileRoutesById {
__root__: typeof rootRoute __root__: typeof rootRoute;
'/': typeof IndexRoute "/": typeof IndexRoute;
'/auth/signin': typeof AuthSigninRoute "/auth/signin": typeof AuthSigninRoute;
'/auth/signup': typeof AuthSignupRoute "/auth/signup": typeof AuthSignupRoute;
'/auth/two-factor': typeof AuthTwoFactorRoute "/auth/two-factor": typeof AuthTwoFactorRoute;
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath fileRoutesByFullPath: FileRoutesByFullPath;
fullPaths: '/' | '/auth/signin' | '/auth/signup' | '/auth/two-factor' fullPaths: "/" | "/auth/signin" | "/auth/signup" | "/auth/two-factor";
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo;
to: '/' | '/auth/signin' | '/auth/signup' | '/auth/two-factor' to: "/" | "/auth/signin" | "/auth/signup" | "/auth/two-factor";
id: '__root__' | '/' | '/auth/signin' | '/auth/signup' | '/auth/two-factor' id: "__root__" | "/" | "/auth/signin" | "/auth/signup" | "/auth/two-factor";
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById;
} }
export interface RootRouteChildren { export interface RootRouteChildren {
IndexRoute: typeof IndexRoute IndexRoute: typeof IndexRoute;
AuthSigninRoute: typeof AuthSigninRoute AuthSigninRoute: typeof AuthSigninRoute;
AuthSignupRoute: typeof AuthSignupRoute AuthSignupRoute: typeof AuthSignupRoute;
AuthTwoFactorRoute: typeof AuthTwoFactorRoute AuthTwoFactorRoute: typeof AuthTwoFactorRoute;
} }
const rootRouteChildren: RootRouteChildren = { const rootRouteChildren: RootRouteChildren = {
@@ -122,11 +122,11 @@ const rootRouteChildren: RootRouteChildren = {
AuthSigninRoute: AuthSigninRoute, AuthSigninRoute: AuthSigninRoute,
AuthSignupRoute: AuthSignupRoute, AuthSignupRoute: AuthSignupRoute,
AuthTwoFactorRoute: AuthTwoFactorRoute, AuthTwoFactorRoute: AuthTwoFactorRoute,
} };
export const routeTree = rootRoute export const routeTree = rootRoute
._addFileChildren(rootRouteChildren) ._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>() ._addFileTypes<FileRouteTypes>();
/* prettier-ignore-end */ /* prettier-ignore-end */

View File

@@ -44,7 +44,7 @@ function RootComponent() {
const [theme, setTheme] = useState<"light" | "dark">("light"); const [theme, setTheme] = useState<"light" | "dark">("light");
const { data, isPending, error } = useSession(); const { data, isPending, error } = useSession();
const { navigate } = useRouter(); const { navigate } = useRouter();
console.log() console.log();
useEffect(() => { useEffect(() => {
if (!data?.user) { if (!data?.user) {
@@ -61,7 +61,6 @@ function RootComponent() {
); );
}, [data, navigate]); }, [data, navigate]);
useEffect(() => { useEffect(() => {
const root = window.document.documentElement; const root = window.document.documentElement;

View File

@@ -1,18 +1,24 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from "@tanstack/react-router";
import { AlertCircle, CheckCircle2 } from 'lucide-react' import { AlertCircle, CheckCircle2 } from "lucide-react";
import { useState } from 'react' import { useState } from "react";
import { Button } from '~/components/ui/button' import { Button } from "~/components/ui/button";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '~/components/ui/card' import {
import { Input } from '~/components/ui/input' Card,
import { Label } from '~/components/ui/label' CardContent,
import { twoFactor } from '~/lib/auth-client' CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { twoFactor } from "~/lib/auth-client";
export const Route = createFileRoute('/auth/two-factor')({ export const Route = createFileRoute("/auth/two-factor")({
component: TwoFactor component: TwoFactor,
}) });
function TwoFactor() {
function TwoFactor(){
const [totpCode, setTotpCode] = useState(""); const [totpCode, setTotpCode] = useState("");
const [error, setError] = useState(""); const [error, setError] = useState("");
const [success, setSuccess] = useState(false); const [success, setSuccess] = useState(false);
@@ -80,5 +86,5 @@ function TwoFactor(){
</CardContent> </CardContent>
</Card> </Card>
</main> </main>
) );
} }

View File

@@ -4,12 +4,12 @@ import {
CardDescription, CardDescription,
CardHeader, CardHeader,
CardTitle, CardTitle,
} from '~/components/ui/card' } from "~/components/ui/card";
import { twoFactor, useSession } from '~/lib/auth-client' import { twoFactor, useSession } from "~/lib/auth-client";
import { UAParser } from 'ua-parser-js' import { UAParser } from "ua-parser-js";
import { Laptop, Loader2, Phone, ShieldCheck, ShieldOff } from 'lucide-react' import { Laptop, Loader2, Phone, ShieldCheck, ShieldOff } from "lucide-react";
import { useState } from 'react' import { useState } from "react";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -18,24 +18,24 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from '~/components/ui/dialog' } from "~/components/ui/dialog";
import { Button } from '~/components/ui/button' import { Button } from "~/components/ui/button";
import { Label } from '~/components/ui/label' import { Label } from "~/components/ui/label";
import { Input } from '~/components/ui/input' import { Input } from "~/components/ui/input";
import { toast } from 'sonner' import { toast } from "sonner";
import QRCode from 'react-qr-code' import QRCode from "react-qr-code";
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute('/')({ export const Route = createFileRoute("/")({
component: Home, component: Home,
}) });
function Home() { function Home() {
const { data } = useSession() const { data } = useSession();
const [twoFactorDialog, setTwoFactorDialog] = useState(false) const [twoFactorDialog, setTwoFactorDialog] = useState(false);
const [twoFaPassword, setTwoFaPassword] = useState('') const [twoFaPassword, setTwoFaPassword] = useState("");
const [isPendingTwoFa, setIsPendingTwoFa] = useState(false) const [isPendingTwoFa, setIsPendingTwoFa] = useState(false);
const [twoFactorVerifyURI, setTwoFactorVerifyURI] = useState<string>('') const [twoFactorVerifyURI, setTwoFactorVerifyURI] = useState<string>("");
return ( return (
<div className="container flex justify-center items-center min-h-[80vh]"> <div className="container flex justify-center items-center min-h-[80vh]">
<Card className="w-fit"> <Card className="w-fit">
@@ -51,12 +51,12 @@ function Home() {
<div className="flex flex-col"> <div className="flex flex-col">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{new UAParser(data.session.userAgent).getDevice().type === {new UAParser(data.session.userAgent).getDevice().type ===
'mobile' ? ( "mobile" ? (
<Phone /> <Phone />
) : ( ) : (
<Laptop size={16} /> <Laptop size={16} />
)} )}
{new UAParser(data.session.userAgent).getOS().name},{' '} {new UAParser(data.session.userAgent).getOS().name},{" "}
{new UAParser(data.session.userAgent).getBrowser().name} {new UAParser(data.session.userAgent).getBrowser().name}
</div> </div>
</div> </div>
@@ -70,8 +70,8 @@ function Home() {
<Button <Button
variant={ variant={
data?.user.twoFactorEnabled data?.user.twoFactorEnabled
? 'destructive' ? "destructive"
: 'outline' : "outline"
} }
className="gap-2" className="gap-2"
> >
@@ -82,8 +82,8 @@ function Home() {
)} )}
<span className="md:text-sm text-xs"> <span className="md:text-sm text-xs">
{data?.user.twoFactorEnabled {data?.user.twoFactorEnabled
? 'Disable 2FA' ? "Disable 2FA"
: 'Enable 2FA'} : "Enable 2FA"}
</span> </span>
</Button> </Button>
</DialogTrigger> </DialogTrigger>
@@ -91,13 +91,13 @@ function Home() {
<DialogHeader> <DialogHeader>
<DialogTitle> <DialogTitle>
{data?.user.twoFactorEnabled {data?.user.twoFactorEnabled
? 'Disable 2FA' ? "Disable 2FA"
: 'Enable 2FA'} : "Enable 2FA"}
</DialogTitle> </DialogTitle>
<DialogDescription> <DialogDescription>
{data?.user.twoFactorEnabled {data?.user.twoFactorEnabled
? 'Disable the second factor authentication from your account' ? "Disable the second factor authentication from your account"
: 'Enable 2FA to secure your account'} : "Enable 2FA to secure your account"}
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
@@ -136,69 +136,68 @@ function Home() {
!twoFactorVerifyURI !twoFactorVerifyURI
) { ) {
toast.error( toast.error(
'Password must be at least 8 characters', "Password must be at least 8 characters",
) );
return return;
} }
setIsPendingTwoFa(true) setIsPendingTwoFa(true);
if (data?.user.twoFactorEnabled) { if (data?.user.twoFactorEnabled) {
const res = await twoFactor.disable({ const res = await twoFactor.disable({
//@ts-ignore //@ts-ignore
password: twoFaPassword, password: twoFaPassword,
fetchOptions: { fetchOptions: {
onError(context) { onError(context) {
toast.error(context.error.message) toast.error(context.error.message);
}, },
onSuccess() { onSuccess() {
toast('2FA disabled successfully') toast("2FA disabled successfully");
setTwoFactorDialog(false) setTwoFactorDialog(false);
}, },
}, },
}) });
} else { } else {
if (twoFactorVerifyURI) { if (twoFactorVerifyURI) {
await twoFactor.verifyTotp({ await twoFactor.verifyTotp({
code: twoFaPassword, code: twoFaPassword,
fetchOptions: { fetchOptions: {
onError(context) { onError(context) {
setIsPendingTwoFa(false) setIsPendingTwoFa(false);
setTwoFaPassword('') setTwoFaPassword("");
toast.error(context.error.message) toast.error(context.error.message);
}, },
onSuccess() { onSuccess() {
toast('2FA enabled successfully') toast("2FA enabled successfully");
setTwoFactorVerifyURI('') setTwoFactorVerifyURI("");
setIsPendingTwoFa(false) setIsPendingTwoFa(false);
setTwoFaPassword('') setTwoFaPassword("");
setTwoFactorDialog(false) setTwoFactorDialog(false);
}, },
}, },
}) });
return return;
} }
await twoFactor.enable({ await twoFactor.enable({
password: twoFaPassword, password: twoFaPassword,
fetchOptions: { fetchOptions: {
onError(context) { onError(context) {
toast.error(context.error.message) toast.error(context.error.message);
}, },
onSuccess(ctx) { onSuccess(ctx) {
setTwoFactorVerifyURI(ctx.data.totpURI) setTwoFactorVerifyURI(ctx.data.totpURI);
}, },
}, },
}) });
} }
setIsPendingTwoFa(false) setIsPendingTwoFa(false);
setTwoFaPassword('') setTwoFaPassword("");
}} }}
> >
{isPendingTwoFa ? ( {isPendingTwoFa ? (
<Loader2 size={15} className="animate-spin" /> <Loader2 size={15} className="animate-spin" />
) : data?.user.twoFactorEnabled ? ( ) : data?.user.twoFactorEnabled ? (
'Disable 2FA' "Disable 2FA"
) : ( ) : (
'Enable 2FA' "Enable 2FA"
)} )}
</Button> </Button>
</DialogFooter> </DialogFooter>
@@ -211,5 +210,5 @@ function Home() {
)} )}
</Card> </Card>
</div> </div>
) );
} }

View File

@@ -3,4 +3,4 @@ export default {
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },
} };

View File

@@ -137,12 +137,10 @@ export const jwt = (options?: JwtOptions) => {
publicKey: JSON.stringify(publicWebKey), publicKey: JSON.stringify(publicWebKey),
privateKey: privateKeyEncryptionEnabled privateKey: privateKeyEncryptionEnabled
? JSON.stringify( ? JSON.stringify(
await symmetricEncrypt( await symmetricEncrypt({
{
key: ctx.context.options.secret!, key: ctx.context.options.secret!,
data: stringifiedPrivateWebKey, data: stringifiedPrivateWebKey,
} }),
),
) )
: stringifiedPrivateWebKey, : stringifiedPrivateWebKey,
createdAt: new Date(), createdAt: new Date(),
@@ -152,12 +150,10 @@ export const jwt = (options?: JwtOptions) => {
} }
let privateWebKey = privateKeyEncryptionEnabled let privateWebKey = privateKeyEncryptionEnabled
? await symmetricDecrypt( ? await symmetricDecrypt({
{
key: ctx.context.options.secret!, key: ctx.context.options.secret!,
data: JSON.parse(key.privateKey), data: JSON.parse(key.privateKey),
} })
)
: key.privateKey; : key.privateKey;
const privateKey = await importJWK(JSON.parse(privateWebKey)); const privateKey = await importJWK(JSON.parse(privateWebKey));