diff --git a/.github/workflows.yml b/.github/workflows.yml new file mode 100644 index 0000000..5b6e442 --- /dev/null +++ b/.github/workflows.yml @@ -0,0 +1,25 @@ +name: Lint +on: + push: + +jobs: + build: + runs-on: ubuntu-22.04 + strategy: + matrix: + node-version: [20] + steps: + - uses: actions/checkout@v4 + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + - name: Install dependencies + run: pnpm install + - name: Run lint + run: pnpm lint \ No newline at end of file diff --git a/ai/custom-middleware.ts b/ai/custom-middleware.ts index 7f60117..00f17e7 100644 --- a/ai/custom-middleware.ts +++ b/ai/custom-middleware.ts @@ -1,3 +1,3 @@ -import { Experimental_LanguageModelV1Middleware } from 'ai'; +import type { Experimental_LanguageModelV1Middleware } from 'ai'; export const customMiddleware: Experimental_LanguageModelV1Middleware = {}; diff --git a/app/(auth)/actions.ts b/app/(auth)/actions.ts index 4197bd4..c2a5afe 100644 --- a/app/(auth)/actions.ts +++ b/app/(auth)/actions.ts @@ -65,16 +65,15 @@ export const register = async ( if (user) { return { status: 'user_exists' } as RegisterActionState; - } else { - await createUser(validatedData.email, validatedData.password); - await signIn('credentials', { - email: validatedData.email, - password: validatedData.password, - redirect: false, - }); - - return { status: 'success' }; } + await createUser(validatedData.email, validatedData.password); + await signIn('credentials', { + email: validatedData.email, + password: validatedData.password, + redirect: false, + }); + + return { status: 'success' }; } catch (error) { if (error instanceof z.ZodError) { return { status: 'invalid_data' }; diff --git a/app/(auth)/auth.ts b/app/(auth)/auth.ts index d49fefe..3d8e738 100644 --- a/app/(auth)/auth.ts +++ b/app/(auth)/auth.ts @@ -1,5 +1,5 @@ import { compare } from 'bcrypt-ts'; -import NextAuth, { User, Session } from 'next-auth'; +import NextAuth, { type User, type Session } from 'next-auth'; import Credentials from 'next-auth/providers/credentials'; import { getUser } from '@/lib/db/queries'; @@ -20,11 +20,13 @@ export const { providers: [ Credentials({ credentials: {}, + // biome-ignore lint/suspicious/noExplicitAny: TODO async authorize({ email, password }: any) { - let users = await getUser(email); + const users = await getUser(email); if (users.length === 0) return null; - let passwordsMatch = await compare(password, users[0].password!); - if (passwordsMatch) return users[0] as any; + const passwordsMatch = await compare(password, users[0].password!); + // biome-ignore lint/suspicious/noExplicitAny: TODO + return users[0] as any; }, }), ], @@ -41,6 +43,7 @@ export const { token, }: { session: ExtendedSession; + // biome-ignore lint/suspicious/noExplicitAny: TODO token: any; }) { if (session.user) { diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index a8e5d8c..e1577dc 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -8,7 +8,7 @@ import { toast } from 'sonner'; import { AuthForm } from '@/components/auth-form'; import { SubmitButton } from '@/components/submit-button'; -import { login, LoginActionState } from '../actions'; +import { login, type LoginActionState } from '../actions'; export default function Page() { const router = useRouter(); diff --git a/app/(chat)/actions.ts b/app/(chat)/actions.ts index 9a1c8fa..e67e36a 100644 --- a/app/(chat)/actions.ts +++ b/app/(chat)/actions.ts @@ -1,6 +1,6 @@ 'use server'; -import { CoreMessage, CoreUserMessage, generateText } from 'ai'; +import { CoreMessage, type CoreUserMessage, generateText } from 'ai'; import { cookies } from 'next/headers'; import { customModel } from '@/ai'; diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index f3b54f7..4f9e01f 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -1,6 +1,6 @@ import { convertToCoreMessages, - Message, + type Message, StreamData, streamObject, streamText, @@ -20,7 +20,7 @@ import { saveMessages, saveSuggestions, } from '@/lib/db/queries'; -import { Suggestion } from '@/lib/db/schema'; +import type { Suggestion } from '@/lib/db/schema'; import { generateUUID, getMostRecentUserMessage, @@ -118,7 +118,7 @@ export async function POST(request: Request) { }), execute: async ({ title }) => { const id = generateUUID(); - let draftText: string = ''; + let draftText = ''; streamingData.append({ type: 'id', @@ -158,7 +158,7 @@ export async function POST(request: Request) { streamingData.append({ type: 'finish', content: '' }); - if (session.user && session.user.id) { + if (session.user?.id) { await saveDocument({ id, title, @@ -170,7 +170,7 @@ export async function POST(request: Request) { return { id, title, - content: `A document was created and is now visible to the user.`, + content: 'A document was created and is now visible to the user.', }; }, }, @@ -192,7 +192,7 @@ export async function POST(request: Request) { } const { content: currentContent } = document; - let draftText: string = ''; + let draftText = ''; streamingData.append({ type: 'clear', @@ -236,7 +236,7 @@ export async function POST(request: Request) { streamingData.append({ type: 'finish', content: '' }); - if (session.user && session.user.id) { + if (session.user?.id) { await saveDocument({ id, title: document.title, @@ -268,7 +268,7 @@ export async function POST(request: Request) { }; } - let suggestions: Array< + const suggestions: Array< Omit > = []; @@ -305,7 +305,7 @@ export async function POST(request: Request) { suggestions.push(suggestion); } - if (session.user && session.user.id) { + if (session.user?.id) { const userId = session.user.id; await saveSuggestions({ @@ -327,7 +327,7 @@ export async function POST(request: Request) { }, }, onFinish: async ({ responseMessages }) => { - if (session.user && session.user.id) { + if (session.user?.id) { try { const responseMessagesWithoutIncompleteToolCalls = sanitizeResponseMessages(responseMessages); diff --git a/app/(chat)/api/document/route.ts b/app/(chat)/api/document/route.ts index 885d39c..9ba2bac 100644 --- a/app/(chat)/api/document/route.ts +++ b/app/(chat)/api/document/route.ts @@ -51,7 +51,7 @@ export async function POST(request: Request) { const { content, title }: { content: string; title: string } = await request.json(); - if (session.user && session.user.id) { + if (session.user?.id) { const document = await saveDocument({ id, content, @@ -60,9 +60,8 @@ export async function POST(request: Request) { }); return Response.json(document, { status: 200 }); - } else { - return new Response('Unauthorized', { status: 401 }); } + return new Response('Unauthorized', { status: 401 }); } export async function PATCH(request: Request) { diff --git a/app/(chat)/api/files/upload/route.ts b/app/(chat)/api/files/upload/route.ts index ab1016b..b753750 100644 --- a/app/(chat)/api/files/upload/route.ts +++ b/app/(chat)/api/files/upload/route.ts @@ -4,9 +4,10 @@ import { z } from 'zod'; import { auth } from '@/app/(auth)/auth'; +// Use Blob instead of File since File is not available in Node.js environment const FileSchema = z.object({ file: z - .instanceof(File) + .instanceof(Blob) .refine((file) => file.size <= 5 * 1024 * 1024, { message: 'File size should be less than 5MB', }) @@ -32,7 +33,7 @@ export async function POST(request: Request) { try { const formData = await request.formData(); - const file = formData.get('file') as File; + const file = formData.get('file') as Blob; if (!file) { return NextResponse.json({ error: 'No file uploaded' }, { status: 400 }); @@ -48,7 +49,8 @@ export async function POST(request: Request) { return NextResponse.json({ error: errorMessage }, { status: 400 }); } - const filename = file.name; + // Get filename from formData since Blob doesn't have name property + const filename = (formData.get('file') as File).name; const fileBuffer = await file.arrayBuffer(); try { diff --git a/app/(chat)/chat/[id]/page.tsx b/app/(chat)/chat/[id]/page.tsx index 060962b..4c175e0 100644 --- a/app/(chat)/chat/[id]/page.tsx +++ b/app/(chat)/chat/[id]/page.tsx @@ -8,7 +8,7 @@ import { Chat as PreviewChat } from '@/components/chat'; import { getChatById, getMessagesByChatId } from '@/lib/db/queries'; import { convertToUIMessages } from '@/lib/utils'; -export default async function Page(props: { params: Promise }) { +export default async function Page(props: { params: Promise<{ id: string }> }) { const params = await props.params; const { id } = params; const chat = await getChatById({ id }); diff --git a/app/layout.tsx b/app/layout.tsx index 8a29480..d0d4c45 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,4 +1,4 @@ -import { Metadata } from 'next'; +import type { Metadata } from 'next'; import { Toaster } from 'sonner'; import { ThemeProvider } from '@/components/theme-provider'; @@ -51,6 +51,7 @@ export default async function RootLayout({ >