Formatting
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
import type { MetadataRoute } from 'next'
|
||||
import type { MetadataRoute } from "next"
|
||||
|
||||
export default function manifest(): MetadataRoute.Manifest {
|
||||
return {
|
||||
name: "Linker - Smart URL Shortener & Link Management",
|
||||
short_name: "Linker",
|
||||
description: "Transform long URLs into short, shareable links. Perfect for social media, emails, and anywhere you need clean, manageable links. Get started for free!",
|
||||
description:
|
||||
"Transform long URLs into short, shareable links. Perfect for social media, emails, and anywhere you need clean, manageable links. Get started for free!",
|
||||
start_url: "/",
|
||||
display: "standalone",
|
||||
icons: [{
|
||||
src: '/favicon.ico',
|
||||
sizes: 'any',
|
||||
type: 'image/x-icon',
|
||||
}],
|
||||
src: "/favicon.ico",
|
||||
sizes: "any",
|
||||
type: "image/x-icon"
|
||||
}]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAllUrls } from '@/lib/db/urls'
|
||||
import type { MetadataRoute } from 'next'
|
||||
import { getAllUrls } from "@/lib/db/urls"
|
||||
import type { MetadataRoute } from "next"
|
||||
|
||||
export default async function robots(): Promise<MetadataRoute.Robots> {
|
||||
const urls = await getAllUrls()
|
||||
@@ -8,7 +8,7 @@ export default async function robots(): Promise<MetadataRoute.Robots> {
|
||||
if (u.crawlable) {
|
||||
return `/r/${u.slug}`
|
||||
}
|
||||
}).filter(v => typeof v === 'string')
|
||||
}).filter(v => typeof v === "string")
|
||||
|
||||
return {
|
||||
rules: [
|
||||
@@ -17,7 +17,8 @@ export default async function robots(): Promise<MetadataRoute.Robots> {
|
||||
allow: "/",
|
||||
disallow: ["/api", "/dasboard", "/sign-in"],
|
||||
crawlDelay: 1
|
||||
}, {
|
||||
},
|
||||
{
|
||||
userAgent: "*",
|
||||
disallow: "/r/",
|
||||
allow: crawlableUrls,
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react"
|
||||
import * as React from "react"
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon,
|
||||
} from "lucide-react"
|
||||
import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button, buttonVariants } from "@/components/ui/button"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Calendar({
|
||||
className,
|
||||
@@ -36,9 +32,8 @@ function Calendar({
|
||||
)}
|
||||
captionLayout={captionLayout}
|
||||
formatters={{
|
||||
formatMonthDropdown: (date) =>
|
||||
date.toLocaleString("default", { month: "short" }),
|
||||
...formatters,
|
||||
formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
|
||||
...formatters
|
||||
}}
|
||||
classNames={{
|
||||
root: cn("w-fit", defaultClassNames.root),
|
||||
@@ -119,7 +114,7 @@ function Calendar({
|
||||
defaultClassNames.disabled
|
||||
),
|
||||
hidden: cn("invisible", defaultClassNames.hidden),
|
||||
...classNames,
|
||||
...classNames
|
||||
}}
|
||||
components={{
|
||||
Root: ({ className, rootRef, ...props }) => {
|
||||
@@ -134,9 +129,7 @@ function Calendar({
|
||||
},
|
||||
Chevron: ({ className, orientation, ...props }) => {
|
||||
if (orientation === "left") {
|
||||
return (
|
||||
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
|
||||
)
|
||||
return <ChevronLeftIcon className={cn("size-4", className)} {...props} />
|
||||
}
|
||||
|
||||
if (orientation === "right") {
|
||||
@@ -148,9 +141,7 @@ function Calendar({
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ChevronDownIcon className={cn("size-4", className)} {...props} />
|
||||
)
|
||||
return <ChevronDownIcon className={cn("size-4", className)} {...props} />
|
||||
},
|
||||
DayButton: CalendarDayButton,
|
||||
WeekNumber: ({ children, ...props }) => {
|
||||
@@ -162,7 +153,7 @@ function Calendar({
|
||||
</td>
|
||||
)
|
||||
},
|
||||
...components,
|
||||
...components
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
@@ -188,12 +179,10 @@ function CalendarDayButton({
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
data-day={day.date.toLocaleDateString()}
|
||||
data-selected-single={
|
||||
modifiers.selected &&
|
||||
data-selected-single={modifiers.selected &&
|
||||
!modifiers.range_start &&
|
||||
!modifiers.range_end &&
|
||||
!modifiers.range_middle
|
||||
}
|
||||
!modifiers.range_middle}
|
||||
data-range-start={modifiers.range_start}
|
||||
data-range-end={modifiers.range_end}
|
||||
data-range-middle={modifiers.range_middle}
|
||||
|
||||
@@ -1,26 +1,18 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import {
|
||||
Controller,
|
||||
FormProvider,
|
||||
useFormContext,
|
||||
useFormState,
|
||||
type ControllerProps,
|
||||
type FieldPath,
|
||||
type FieldValues,
|
||||
} from "react-hook-form"
|
||||
import * as React from "react"
|
||||
import { Controller, type ControllerProps, type FieldPath, type FieldValues, FormProvider, useFormContext, useFormState } from "react-hook-form"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Form = FormProvider
|
||||
|
||||
type FormFieldContextValue<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
||||
> = {
|
||||
name: TName
|
||||
}
|
||||
@@ -31,7 +23,7 @@ const FormFieldContext = React.createContext<FormFieldContextValue>(
|
||||
|
||||
const FormField = <
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
||||
>({
|
||||
...props
|
||||
}: ControllerProps<TFieldValues, TName>) => {
|
||||
@@ -61,7 +53,7 @@ const useFormField = () => {
|
||||
formItemId: `${id}-form-item`,
|
||||
formDescriptionId: `${id}-form-item-description`,
|
||||
formMessageId: `${id}-form-item-message`,
|
||||
...fieldState,
|
||||
...fieldState
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +103,9 @@ function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
|
||||
<Slot
|
||||
data-slot="form-control"
|
||||
id={formItemId}
|
||||
aria-describedby={
|
||||
!error
|
||||
aria-describedby={!error
|
||||
? `${formDescriptionId}`
|
||||
: `${formDescriptionId} ${formMessageId}`
|
||||
}
|
||||
: `${formDescriptionId} ${formMessageId}`}
|
||||
aria-invalid={!!error}
|
||||
{...props}
|
||||
/>
|
||||
@@ -155,13 +145,4 @@ function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
useFormField,
|
||||
Form,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormMessage,
|
||||
FormField,
|
||||
}
|
||||
export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
@@ -45,4 +45,4 @@ function PopoverAnchor({
|
||||
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
||||
}
|
||||
|
||||
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
||||
export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as SheetPrimitive from "@radix-ui/react-dialog"
|
||||
import { XIcon } from "lucide-react"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
@@ -127,13 +127,4 @@ function SheetDescription({
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Sheet,
|
||||
SheetTrigger,
|
||||
SheetClose,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetFooter,
|
||||
SheetTitle,
|
||||
SheetDescription,
|
||||
}
|
||||
export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger }
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, VariantProps } from "class-variance-authority"
|
||||
import { PanelLeftIcon } from "lucide-react"
|
||||
import * as React from "react"
|
||||
|
||||
import { useIsMobile } from "@/hooks/use-mobile"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetDescription,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
} from "@/components/ui/sheet"
|
||||
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip"
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useIsMobile } from "@/hooks/use-mobile"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const SIDEBAR_COOKIE_NAME = "sidebar_state"
|
||||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
||||
@@ -121,7 +110,7 @@ function SidebarProvider({
|
||||
isMobile,
|
||||
openMobile,
|
||||
setOpenMobile,
|
||||
toggleSidebar,
|
||||
toggleSidebar
|
||||
}),
|
||||
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
|
||||
)
|
||||
@@ -131,13 +120,11 @@ function SidebarProvider({
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<div
|
||||
data-slot="sidebar-wrapper"
|
||||
style={
|
||||
{
|
||||
style={{
|
||||
"--sidebar-width": SIDEBAR_WIDTH,
|
||||
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
|
||||
...style,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
...style
|
||||
} as React.CSSProperties}
|
||||
className={cn(
|
||||
"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full",
|
||||
className
|
||||
@@ -188,11 +175,9 @@ function Sidebar({
|
||||
data-slot="sidebar"
|
||||
data-mobile="true"
|
||||
className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
|
||||
style={
|
||||
{
|
||||
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
style={{
|
||||
"--sidebar-width": SIDEBAR_WIDTH_MOBILE
|
||||
} as React.CSSProperties}
|
||||
side={side}
|
||||
>
|
||||
<SheetHeader className="sr-only">
|
||||
@@ -480,18 +465,18 @@ const sidebarMenuButtonVariants = cva(
|
||||
variant: {
|
||||
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
||||
outline:
|
||||
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
|
||||
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]"
|
||||
},
|
||||
size: {
|
||||
default: "h-8 text-sm",
|
||||
sm: "h-7 text-xs",
|
||||
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!",
|
||||
},
|
||||
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
size: "default"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -528,7 +513,7 @@ function SidebarMenuButton({
|
||||
|
||||
if (typeof tooltip === "string") {
|
||||
tooltip = {
|
||||
children: tooltip,
|
||||
children: tooltip
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,11 +612,9 @@ function SidebarMenuSkeleton({
|
||||
<Skeleton
|
||||
className="h-4 max-w-(--skeleton-width) flex-1"
|
||||
data-sidebar="menu-skeleton-text"
|
||||
style={
|
||||
{
|
||||
"--skeleton-width": width,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
style={{
|
||||
"--skeleton-width": width
|
||||
} as React.CSSProperties}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
@@ -722,5 +705,5 @@ export {
|
||||
SidebarRail,
|
||||
SidebarSeparator,
|
||||
SidebarTrigger,
|
||||
useSidebar,
|
||||
useSidebar
|
||||
}
|
||||
|
||||
@@ -10,13 +10,11 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
||||
<Sonner
|
||||
theme={theme as ToasterProps["theme"]}
|
||||
className="toaster group"
|
||||
style={
|
||||
{
|
||||
style={{
|
||||
"--normal-bg": "var(--popover)",
|
||||
"--normal-text": "var(--popover-foreground)",
|
||||
"--normal-border": "var(--border)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
"--normal-border": "var(--border)"
|
||||
} as React.CSSProperties}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as SwitchPrimitive from "@radix-ui/react-switch"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
|
||||
@@ -104,13 +104,4 @@ function TableCaption({
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Table,
|
||||
TableHeader,
|
||||
TableBody,
|
||||
TableFooter,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableCell,
|
||||
TableCaption,
|
||||
}
|
||||
export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
@@ -58,4 +58,4 @@ function TooltipContent({
|
||||
)
|
||||
}
|
||||
|
||||
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
||||
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use server"
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { getSession } from "../auth/session"
|
||||
import { insertUrl } from "../db/urls"
|
||||
import { advancedUrlSchema, editUrlSchema, urlFormSchema } from "../schema/url"
|
||||
import { deleteUrl as deleteUrlDb, updateUrl as updateUrlDb } from "../db/urls"
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { advancedUrlSchema, editUrlSchema, urlFormSchema } from "../schema/url"
|
||||
import { getWebsiteTitle } from "../websiteTitle"
|
||||
|
||||
type Response = {
|
||||
@@ -68,7 +68,7 @@ export async function createAdvanceUrl(unsafeData: unknown): Promise<Response> {
|
||||
...data,
|
||||
slug: data.slug?.length === 0 ? undefined : data.slug,
|
||||
title: data.title?.length === 0 ? await getWebsiteTitle(data.url) : data.title,
|
||||
maxVisits: data.maxVisits > 0 ? data.maxVisits : undefined,
|
||||
maxVisits: data.maxVisits > 0 ? data.maxVisits : undefined
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { betterAuth } from "better-auth"
|
||||
import { drizzleAdapter } from "better-auth/adapters/drizzle"
|
||||
import { nextCookies } from "better-auth/next-js"
|
||||
import { genericOAuth } from "better-auth/plugins"
|
||||
import { db } from "../drizzle/db"
|
||||
import { env } from "../env/server"
|
||||
import { nextCookies } from "better-auth/next-js"
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: drizzleAdapter(db, {
|
||||
@@ -18,6 +18,6 @@ export const auth = betterAuth({
|
||||
clientSecret: env.AUTHENTIK_CLIENT_SECRET,
|
||||
discoveryUrl: env.AUTHENTIK_DISCOVERY_URL
|
||||
}]
|
||||
}),
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { headers } from "next/headers"
|
||||
import { auth } from "./auth"
|
||||
import { redirect } from "next/navigation"
|
||||
import { auth } from "./auth"
|
||||
|
||||
export async function getSession() {
|
||||
const session = await auth.api.getSession({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { eq, desc, count } from "drizzle-orm";
|
||||
import { db } from "../drizzle/db";
|
||||
import { urls, visits } from "../drizzle/schema";
|
||||
import { cacheTag } from "next/dist/server/use-cache/cache-tag";
|
||||
import { revalidateTag } from "next/cache";
|
||||
import { count, desc, eq } from "drizzle-orm"
|
||||
import { revalidateTag } from "next/cache"
|
||||
import { cacheTag } from "next/dist/server/use-cache/cache-tag"
|
||||
import { db } from "../drizzle/db"
|
||||
import { urls, visits } from "../drizzle/schema"
|
||||
|
||||
export async function getAllUrls() {
|
||||
"use cache"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
export function generateRandomSlug(): string {
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let result = '';
|
||||
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
let result = ""
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * characters.length));
|
||||
result += characters.charAt(Math.floor(Math.random() * characters.length))
|
||||
}
|
||||
|
||||
return result;
|
||||
return result
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { z } from "zod";
|
||||
import { z } from "zod"
|
||||
|
||||
export const urlFormSchema = z.object({
|
||||
url: z.string().url("Please enter a valid URL"),
|
||||
@@ -12,7 +12,7 @@ export const advancedUrlSchema = z.object({
|
||||
maxVisits: z.number().int().positive().nullable(),
|
||||
expDate: z.date().optional(),
|
||||
forwardQueryParams: z.boolean(),
|
||||
crawlable: z.boolean(),
|
||||
crawlable: z.boolean()
|
||||
})
|
||||
|
||||
export const editUrlSchema = z.object({
|
||||
@@ -22,5 +22,5 @@ export const editUrlSchema = z.object({
|
||||
maxVisits: z.number().int().positive().nullable(),
|
||||
expDate: z.date().nullable(),
|
||||
forwardQueryParams: z.boolean(),
|
||||
crawlable: z.boolean(),
|
||||
crawlable: z.boolean()
|
||||
})
|
||||
@@ -1,12 +1,12 @@
|
||||
export async function getWebsiteTitle(url: string): Promise<string | null> {
|
||||
const res = await fetch(url, { redirect: 'follow' })
|
||||
const res = await fetch(url, { redirect: "follow" })
|
||||
|
||||
if (!res.ok) {
|
||||
return null
|
||||
}
|
||||
|
||||
const contentType = res.headers.get('content-type')
|
||||
if (!contentType || !contentType.includes('text/html')) {
|
||||
const contentType = res.headers.get("content-type")
|
||||
if (!contentType || !contentType.includes("text/html")) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@ export async function getWebsiteTitle(url: string): Promise<string | null> {
|
||||
|
||||
if (titleMatch && titleMatch[1]) {
|
||||
const title = titleMatch[1]
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/&/g, "&")
|
||||
.replace(/"/g, "\"")
|
||||
.replace(/'/g, "'")
|
||||
.replace(/ /g, ' ')
|
||||
.replace(/ /g, " ")
|
||||
.trim()
|
||||
|
||||
return title || null
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { getSessionCookie } from "better-auth/cookies";
|
||||
import { getSessionCookie } from "better-auth/cookies"
|
||||
import { NextRequest, NextResponse } from "next/server"
|
||||
|
||||
export async function middleware(request: NextRequest) {
|
||||
const sessionCookie = getSessionCookie(request);
|
||||
const sessionCookie = getSessionCookie(request)
|
||||
if (!sessionCookie) {
|
||||
return NextResponse.redirect(new URL("/", request.url));
|
||||
return NextResponse.redirect(new URL("/", request.url))
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
return NextResponse.next()
|
||||
}
|
||||
|
||||
export const config = { matcher: ["/dashboard"] };
|
||||
export const config = { matcher: ["/dashboard"] }
|
||||
|
||||
Reference in New Issue
Block a user