Gardening (#540)

This commit is contained in:
Jared Palmer 2024-11-15 11:12:05 -05:00 committed by GitHub
commit f23c73f6a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
65 changed files with 457 additions and 325 deletions

View file

@ -6,29 +6,10 @@
"prettier", "prettier",
"plugin:tailwindcss/recommended" "plugin:tailwindcss/recommended"
], ],
"plugins": ["import", "tailwindcss"], "plugins": ["tailwindcss"],
"rules": { "rules": {
"tailwindcss/no-custom-classname": "off", "tailwindcss/no-custom-classname": "off",
"tailwindcss/classnames-order": "off", "tailwindcss/classnames-order": "off"
"import/order": [
"error",
{
"groups": [
"builtin",
"external",
"internal",
["parent", "sibling"],
"index",
"object",
"type"
],
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
]
}, },
"settings": { "settings": {
"import/resolver": { "import/resolver": {

View file

@ -2,7 +2,7 @@
import { z } from 'zod'; import { z } from 'zod';
import { createUser, getUser } from '@/db/queries'; import { createUser, getUser } from '@/lib/db/queries';
import { signIn } from './auth'; import { signIn } from './auth';
@ -61,7 +61,7 @@ export const register = async (
password: formData.get('password'), password: formData.get('password'),
}); });
let [user] = await getUser(validatedData.email); const [user] = await getUser(validatedData.email);
if (user) { if (user) {
return { status: 'user_exists' } as RegisterActionState; return { status: 'user_exists' } as RegisterActionState;

View file

@ -1,4 +1,4 @@
import { NextAuthConfig } from 'next-auth'; import type { NextAuthConfig } from 'next-auth';
export const authConfig = { export const authConfig = {
pages: { pages: {
@ -11,10 +11,10 @@ export const authConfig = {
], ],
callbacks: { callbacks: {
authorized({ auth, request: { nextUrl } }) { authorized({ auth, request: { nextUrl } }) {
let isLoggedIn = !!auth?.user; const isLoggedIn = !!auth?.user;
let isOnChat = nextUrl.pathname.startsWith('/'); const isOnChat = nextUrl.pathname.startsWith('/');
let isOnRegister = nextUrl.pathname.startsWith('/register'); const isOnRegister = nextUrl.pathname.startsWith('/register');
let isOnLogin = nextUrl.pathname.startsWith('/login'); const isOnLogin = nextUrl.pathname.startsWith('/login');
if (isLoggedIn && (isOnLogin || isOnRegister)) { if (isLoggedIn && (isOnLogin || isOnRegister)) {
return Response.redirect(new URL('/', nextUrl as unknown as URL)); return Response.redirect(new URL('/', nextUrl as unknown as URL));

View file

@ -2,7 +2,7 @@ import { compare } from 'bcrypt-ts';
import NextAuth, { User, Session } from 'next-auth'; import NextAuth, { User, Session } from 'next-auth';
import Credentials from 'next-auth/providers/credentials'; import Credentials from 'next-auth/providers/credentials';
import { getUser } from '@/db/queries'; import { getUser } from '@/lib/db/queries';
import { authConfig } from './auth.config'; import { authConfig } from './auth.config';

View file

@ -5,8 +5,8 @@ import { useRouter } from 'next/navigation';
import { useActionState, useEffect, useState } from 'react'; import { useActionState, useEffect, useState } from 'react';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { AuthForm } from '@/components/custom/auth-form'; import { AuthForm } from '@/components/auth-form';
import { SubmitButton } from '@/components/custom/submit-button'; import { SubmitButton } from '@/components/submit-button';
import { login, LoginActionState } from '../actions'; import { login, LoginActionState } from '../actions';

View file

@ -5,10 +5,10 @@ import { useRouter } from 'next/navigation';
import { useActionState, useEffect, useState } from 'react'; import { useActionState, useEffect, useState } from 'react';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { AuthForm } from '@/components/custom/auth-form'; import { AuthForm } from '@/components/auth-form';
import { SubmitButton } from '@/components/custom/submit-button'; import { SubmitButton } from '@/components/submit-button';
import { register, RegisterActionState } from '../actions'; import { register, type RegisterActionState } from '../actions';
export default function Page() { export default function Page() {
const router = useRouter(); const router = useRouter();

View file

@ -16,7 +16,7 @@ export async function generateTitleFromUserMessage({
message: CoreUserMessage; message: CoreUserMessage;
}) { }) {
const { text: title } = await generateText({ const { text: title } = await generateText({
model: customModel('gpt-3.5-turbo'), model: customModel('gpt-4o-mini'),
system: `\n system: `\n
- you will generate a short title based on the first message a user begins a conversation with - you will generate a short title based on the first message a user begins a conversation with
- ensure it is not more than 80 characters long - ensure it is not more than 80 characters long

View file

@ -19,8 +19,8 @@ import {
saveDocument, saveDocument,
saveMessages, saveMessages,
saveSuggestions, saveSuggestions,
} from '@/db/queries'; } from '@/lib/db/queries';
import { Suggestion } from '@/db/schema'; import { Suggestion } from '@/lib/db/schema';
import { import {
generateUUID, generateUUID,
getMostRecentUserMessage, getMostRecentUserMessage,

View file

@ -3,7 +3,7 @@ import {
deleteDocumentsByIdAfterTimestamp, deleteDocumentsByIdAfterTimestamp,
getDocumentsById, getDocumentsById,
saveDocument, saveDocument,
} from '@/db/queries'; } from '@/lib/db/queries';
export async function GET(request: Request) { export async function GET(request: Request) {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);

View file

@ -1,5 +1,5 @@
import { auth } from '@/app/(auth)/auth'; import { auth } from '@/app/(auth)/auth';
import { getChatsByUserId } from '@/db/queries'; import { getChatsByUserId } from '@/lib/db/queries';
export async function GET() { export async function GET() {
const session = await auth(); const session = await auth();

View file

@ -1,5 +1,5 @@
import { auth } from '@/app/(auth)/auth'; import { auth } from '@/app/(auth)/auth';
import { getSuggestionsByDocumentId } from '@/db/queries'; import { getSuggestionsByDocumentId } from '@/lib/db/queries';
export async function GET(request: Request) { export async function GET(request: Request) {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);

View file

@ -1,5 +1,5 @@
import { auth } from '@/app/(auth)/auth'; import { auth } from '@/app/(auth)/auth';
import { getVotesByChatId, voteMessage } from '@/db/queries'; import { getVotesByChatId, voteMessage } from '@/lib/db/queries';
export async function GET(request: Request) { export async function GET(request: Request) {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);

View file

@ -4,8 +4,8 @@ import { notFound } from 'next/navigation';
import { DEFAULT_MODEL_NAME, models } from '@/ai/models'; import { DEFAULT_MODEL_NAME, models } from '@/ai/models';
import { auth } from '@/app/(auth)/auth'; import { auth } from '@/app/(auth)/auth';
import { Chat as PreviewChat } from '@/components/custom/chat'; import { Chat as PreviewChat } from '@/components/chat';
import { getChatById, getMessagesByChatId } from '@/db/queries'; import { getChatById, getMessagesByChatId } from '@/lib/db/queries';
import { convertToUIMessages } from '@/lib/utils'; import { convertToUIMessages } from '@/lib/utils';
export default async function Page(props: { params: Promise<any> }) { export default async function Page(props: { params: Promise<any> }) {

View file

@ -1,6 +1,6 @@
import { cookies } from 'next/headers'; import { cookies } from 'next/headers';
import { AppSidebar } from '@/components/custom/app-sidebar'; import { AppSidebar } from '@/components/app-sidebar';
import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar'; import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar';
import { auth } from '../(auth)/auth'; import { auth } from '../(auth)/auth';

View file

@ -1,7 +1,7 @@
import { cookies } from 'next/headers'; import { cookies } from 'next/headers';
import { DEFAULT_MODEL_NAME, models } from '@/ai/models'; import { DEFAULT_MODEL_NAME, models } from '@/ai/models';
import { Chat } from '@/components/custom/chat'; import { Chat } from '@/components/chat';
import { generateUUID } from '@/lib/utils'; import { generateUUID } from '@/lib/utils';
export default async function Page() { export default async function Page() {

View file

@ -104,17 +104,17 @@
} }
@font-face { @font-face {
font-family: 'geist'; font-family: "geist";
font-style: normal; font-style: normal;
font-weight: 100 900; font-weight: 100 900;
src: url(/fonts/geist.woff2) format('woff2'); src: url(/fonts/geist.woff2) format("woff2");
} }
@font-face { @font-face {
font-family: 'geist-mono'; font-family: "geist-mono";
font-style: normal; font-style: normal;
font-weight: 100 900; font-weight: 100 900;
src: url(/fonts/geist-mono.woff2) format('woff2'); src: url(/fonts/geist-mono.woff2) format("woff2");
} }
} }
@ -123,7 +123,7 @@
pointer-events: none !important; pointer-events: none !important;
} }
*[class^='text-'] { *[class^="text-"] {
color: transparent; color: transparent;
@apply rounded-md bg-foreground/20 select-none animate-pulse; @apply rounded-md bg-foreground/20 select-none animate-pulse;
} }

View file

@ -1,7 +1,7 @@
import { Metadata } from 'next'; import { Metadata } from 'next';
import { Toaster } from 'sonner'; import { Toaster } from 'sonner';
import { ThemeProvider } from '@/components/custom/theme-provider'; import { ThemeProvider } from '@/components/theme-provider';
import './globals.css'; import './globals.css';

58
biome.json Normal file
View file

@ -0,0 +1,58 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": true },
"files": {
"ignoreUnknown": false,
"ignore": [
"**/pnpm-lock.yaml",
"lib/db/migrations",
"lib/editor/react-renderer.tsx",
"node_modules",
".next",
"public",
".vercel"
]
},
"formatter": {
"enabled": true,
"useEditorconfig": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 80,
"attributePosition": "auto",
"bracketSpacing": true,
"ignore": ["**/pnpm-lock.yaml", "lib/db/drizzle"]
},
"organizeImports": { "enabled": true },
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"a11y": {
"noSvgWithoutTitle": "off",
"useKeyWithClickEvents": "off"
},
"style": {
"noNonNullAssertion": "off"
},
"correctness": {
"useExhaustiveDependencies": "off"
}
}
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "es5",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSameLine": false,
"quoteStyle": "single",
"attributePosition": "auto",
"bracketSpacing": true
}
}
}

View file

@ -4,9 +4,9 @@ import Link from 'next/link';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { type User } from 'next-auth'; import { type User } from 'next-auth';
import { PlusIcon } from '@/components/custom/icons'; import { PlusIcon } from '@/components/icons';
import { SidebarHistory } from '@/components/custom/sidebar-history'; import { SidebarHistory } from '@/components/sidebar-history';
import { SidebarUserNav } from '@/components/custom/sidebar-user-nav'; import { SidebarUserNav } from '@/components/sidebar-user-nav';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {
Sidebar, Sidebar,

View file

@ -1,7 +1,7 @@
import Form from 'next/form'; import Form from 'next/form';
import { Input } from '../ui/input'; import { Input } from './ui/input';
import { Label } from '../ui/label'; import { Label } from './ui/label';
export function AuthForm({ export function AuthForm({
action, action,

View file

@ -17,7 +17,7 @@ import {
useWindowSize, useWindowSize,
} from 'usehooks-ts'; } from 'usehooks-ts';
import { Document, Suggestion, Vote } from '@/db/schema'; import { Document, Suggestion, Vote } from '@/lib/db/schema';
import { fetcher } from '@/lib/utils'; import { fetcher } from '@/lib/utils';
import { DiffView } from './diffview'; import { DiffView } from './diffview';
@ -27,10 +27,10 @@ import { CopyIcon, CrossIcon, DeltaIcon, RedoIcon, UndoIcon } from './icons';
import { PreviewMessage } from './message'; import { PreviewMessage } from './message';
import { MultimodalInput } from './multimodal-input'; import { MultimodalInput } from './multimodal-input';
import { Toolbar } from './toolbar'; import { Toolbar } from './toolbar';
import { Button } from './ui/button';
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip';
import { useScrollToBottom } from './use-scroll-to-bottom'; import { useScrollToBottom } from './use-scroll-to-bottom';
import { VersionFooter } from './version-footer'; import { VersionFooter } from './version-footer';
import { Button } from '../ui/button';
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
export interface UIBlock { export interface UIBlock {
title: string; title: string;
documentId: string; documentId: string;

View file

@ -4,13 +4,13 @@ import Link from 'next/link';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { useWindowSize } from 'usehooks-ts'; import { useWindowSize } from 'usehooks-ts';
import { ModelSelector } from '@/components/custom/model-selector'; import { ModelSelector } from '@/components/model-selector';
import { SidebarToggle } from '@/components/custom/sidebar-toggle'; import { SidebarToggle } from '@/components/sidebar-toggle';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { BetterTooltip } from '@/components/ui/tooltip'; import { BetterTooltip } from '@/components/ui/tooltip';
import { PlusIcon, VercelIcon } from './icons'; import { PlusIcon, VercelIcon } from './icons';
import { useSidebar } from '../ui/sidebar'; import { useSidebar } from './ui/sidebar';
export function ChatHeader({ selectedModelId }: { selectedModelId: string }) { export function ChatHeader({ selectedModelId }: { selectedModelId: string }) {
const router = useRouter(); const router = useRouter();

View file

@ -7,10 +7,10 @@ import { useState } from 'react';
import useSWR, { useSWRConfig } from 'swr'; import useSWR, { useSWRConfig } from 'swr';
import { useWindowSize } from 'usehooks-ts'; import { useWindowSize } from 'usehooks-ts';
import { ChatHeader } from '@/components/custom/chat-header'; import { ChatHeader } from '@/components/chat-header';
import { PreviewMessage, ThinkingMessage } from '@/components/custom/message'; import { PreviewMessage, ThinkingMessage } from '@/components/message';
import { useScrollToBottom } from '@/components/custom/use-scroll-to-bottom'; import { useScrollToBottom } from '@/components/use-scroll-to-bottom';
import { Vote } from '@/db/schema'; import { Vote } from '@/lib/db/schema';
import { fetcher } from '@/lib/utils'; import { fetcher } from '@/lib/utils';
import { Block, UIBlock } from './block'; import { Block, UIBlock } from './block';

View file

@ -6,7 +6,7 @@ import { EditorState } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view'; import { EditorView } from 'prosemirror-view';
import React, { memo, useEffect, useRef } from 'react'; import React, { memo, useEffect, useRef } from 'react';
import { Suggestion } from '@/db/schema'; import { Suggestion } from '@/lib/db/schema';
import { import {
documentSchema, documentSchema,
handleTransaction, handleTransaction,

View file

@ -3,17 +3,17 @@ import { toast } from 'sonner';
import { useSWRConfig } from 'swr'; import { useSWRConfig } from 'swr';
import { useCopyToClipboard } from 'usehooks-ts'; import { useCopyToClipboard } from 'usehooks-ts';
import { Vote } from '@/db/schema'; import { Vote } from '@/lib/db/schema';
import { getMessageIdFromAnnotations } from '@/lib/utils'; import { getMessageIdFromAnnotations } from '@/lib/utils';
import { CopyIcon, ThumbDownIcon, ThumbUpIcon } from './icons'; import { CopyIcon, ThumbDownIcon, ThumbUpIcon } from './icons';
import { Button } from '../ui/button'; import { Button } from './ui/button';
import { import {
Tooltip, Tooltip,
TooltipContent, TooltipContent,
TooltipProvider, TooltipProvider,
TooltipTrigger, TooltipTrigger,
} from '../ui/tooltip'; } from './ui/tooltip';
export function MessageActions({ export function MessageActions({
chatId, chatId,

View file

@ -5,7 +5,7 @@ import cx from 'classnames';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { Dispatch, SetStateAction } from 'react'; import { Dispatch, SetStateAction } from 'react';
import { Vote } from '@/db/schema'; import { Vote } from '@/lib/db/schema';
import { UIBlock } from './block'; import { UIBlock } from './block';
import { DocumentToolCall, DocumentToolResult } from './document'; import { DocumentToolCall, DocumentToolResult } from './document';

View file

@ -19,8 +19,8 @@ import { sanitizeUIMessages } from '@/lib/utils';
import { ArrowUpIcon, PaperclipIcon, StopIcon } from './icons'; import { ArrowUpIcon, PaperclipIcon, StopIcon } from './icons';
import { PreviewAttachment } from './preview-attachment'; import { PreviewAttachment } from './preview-attachment';
import { Button } from '../ui/button'; import { Button } from './ui/button';
import { Textarea } from '../ui/textarea'; import { Textarea } from './ui/textarea';
const suggestedActions = [ const suggestedActions = [
{ {

View file

@ -8,7 +8,7 @@ import { useEffect, useState } from 'react';
import { toast } from 'sonner'; import { toast } from 'sonner';
import useSWR from 'swr'; import useSWR from 'swr';
import { MoreHorizontalIcon, TrashIcon } from '@/components/custom/icons'; import { MoreHorizontalIcon, TrashIcon } from '@/components/icons';
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@ -34,7 +34,7 @@ import {
SidebarMenuItem, SidebarMenuItem,
useSidebar, useSidebar,
} from '@/components/ui/sidebar'; } from '@/components/ui/sidebar';
import { Chat } from '@/db/schema'; import { Chat } from '@/lib/db/schema';
import { fetcher } from '@/lib/utils'; import { fetcher } from '@/lib/utils';
type GroupedChats = { type GroupedChats = {

View file

@ -5,7 +5,7 @@ import { BetterTooltip } from '@/components/ui/tooltip';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { SidebarLeftIcon } from './icons'; import { SidebarLeftIcon } from './icons';
import { Button } from '../ui/button'; import { Button } from './ui/button';
export function SidebarToggle({ export function SidebarToggle({
className, className,

View file

@ -2,9 +2,9 @@
import { useFormStatus } from 'react-dom'; import { useFormStatus } from 'react-dom';
import { LoaderIcon } from '@/components/custom/icons'; import { LoaderIcon } from '@/components/icons';
import { Button } from '../ui/button'; import { Button } from './ui/button';
export function SubmitButton({ export function SubmitButton({
children, children,

View file

@ -7,7 +7,7 @@ import { useWindowSize } from 'usehooks-ts';
import { UISuggestion } from '@/lib/editor/suggestions'; import { UISuggestion } from '@/lib/editor/suggestions';
import { CrossIcon, MessageIcon } from './icons'; import { CrossIcon, MessageIcon } from './icons';
import { Button } from '../ui/button'; import { Button } from './ui/button';
export const Suggestion = ({ export const Suggestion = ({
suggestion, suggestion,

View file

@ -26,7 +26,7 @@ import {
StopIcon, StopIcon,
SummarizeIcon, SummarizeIcon,
} from './icons'; } from './icons';
import { Button } from '../ui/button'; import { Button } from './ui/button';
type ToolProps = { type ToolProps = {
type: 'final-polish' | 'request-suggestions' | 'adjust-reading-level'; type: 'final-polish' | 'request-suggestions' | 'adjust-reading-level';

View file

@ -2,7 +2,7 @@ import { JSONValue } from 'ai';
import { Dispatch, SetStateAction, useEffect, useState } from 'react'; import { Dispatch, SetStateAction, useEffect, useState } from 'react';
import { useSWRConfig } from 'swr'; import { useSWRConfig } from 'swr';
import { Suggestion } from '@/db/schema'; import { Suggestion } from '@/lib/db/schema';
import { UIBlock } from './block'; import { UIBlock } from './block';

View file

@ -6,12 +6,12 @@ import { useState } from 'react';
import { useSWRConfig } from 'swr'; import { useSWRConfig } from 'swr';
import { useWindowSize } from 'usehooks-ts'; import { useWindowSize } from 'usehooks-ts';
import { Document } from '@/db/schema'; import { Document } from '@/lib/db/schema';
import { getDocumentTimestampByIndex } from '@/lib/utils'; import { getDocumentTimestampByIndex } from '@/lib/utils';
import { UIBlock } from './block'; import { UIBlock } from './block';
import { LoaderIcon } from './icons'; import { LoaderIcon } from './icons';
import { Button } from '../ui/button'; import { Button } from './ui/button';
interface VersionFooterProps { interface VersionFooterProps {
block: UIBlock; block: UIBlock;

View file

@ -6,8 +6,8 @@ config({
}); });
export default defineConfig({ export default defineConfig({
schema: './db/schema.ts', schema: './lib/db/schema.ts',
out: './lib/drizzle', out: './lib/db/migrations',
dialect: 'postgresql', dialect: 'postgresql',
dbCredentials: { dbCredentials: {
url: process.env.POSTGRES_URL!, url: process.env.POSTGRES_URL!,

View file

@ -5,7 +5,7 @@ import { DOMParser, Node } from 'prosemirror-model';
import { Decoration, DecorationSet, EditorView } from 'prosemirror-view'; import { Decoration, DecorationSet, EditorView } from 'prosemirror-view';
import { renderToString } from 'react-dom/server'; import { renderToString } from 'react-dom/server';
import { Markdown } from '@/components/custom/markdown'; import { Markdown } from '@/components/markdown';
import { documentSchema } from './config'; import { documentSchema } from './config';
import { createSuggestionWidget, UISuggestion } from './suggestions'; import { createSuggestionWidget, UISuggestion } from './suggestions';

View file

@ -3,8 +3,8 @@ import { PluginKey, Plugin } from 'prosemirror-state';
import { Decoration, DecorationSet, EditorView } from 'prosemirror-view'; import { Decoration, DecorationSet, EditorView } from 'prosemirror-view';
import { createRoot } from 'react-dom/client'; import { createRoot } from 'react-dom/client';
import { Suggestion as PreviewSuggestion } from '@/components/custom/suggestion'; import { Suggestion as PreviewSuggestion } from '@/components/suggestion';
import { Suggestion } from '@/db/schema'; import { Suggestion } from '@/lib/db/schema';
export interface UISuggestion extends Suggestion { export interface UISuggestion extends Suggestion {
selectionStart: number; selectionStart: number;

View file

@ -8,7 +8,7 @@ import {
import { clsx, type ClassValue } from 'clsx'; import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
import { Message as DBMessage, Document } from '@/db/schema'; import { Message as DBMessage, Document } from '@/lib/db/schema';
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)); return twMerge(clsx(inputs));

View file

@ -4,10 +4,14 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev --turbo", "dev": "next dev --turbo",
"build": "tsx db/migrate && next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint",
"format": "prettier --write ." "lint:fix": "next lint --fix",
"format": "biome format --write",
"db:generate": "drizzle-kit generate",
"db:migrate": "npx tsx lib/db/migrate.ts",
"db:studio": "drizzle-kit studio"
}, },
"dependencies": { "dependencies": {
"@ai-sdk/openai": "1.0.0-canary.3", "@ai-sdk/openai": "1.0.0-canary.3",
@ -62,9 +66,10 @@
"zod": "^3.23.8" "zod": "^3.23.8"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "1.9.4",
"@tailwindcss/typography": "^0.5.15", "@tailwindcss/typography": "^0.5.15",
"@types/d3-scale": "^4.0.8", "@types/d3-scale": "^4.0.8",
"@types/node": "^20", "@types/node": "^22.8.6",
"@types/pdf-parse": "^1.1.4", "@types/pdf-parse": "^1.1.4",
"@types/react": "^18", "@types/react": "^18",
"@types/react-dom": "^18", "@types/react-dom": "^18",
@ -73,10 +78,8 @@
"eslint-config-next": "14.2.5", "eslint-config-next": "14.2.5",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.3", "eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-tailwindcss": "^3.17.5", "eslint-plugin-tailwindcss": "^3.17.5",
"postcss": "^8", "postcss": "^8",
"prettier": "^3.3.3",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"tsx": "^4.19.1", "tsx": "^4.19.1",
"typescript": "^5" "typescript": "^5"

543
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,9 +0,0 @@
/** @type {import('prettier').Config} */
module.exports = {
endOfLine: 'lf',
semi: true,
useTabs: false,
singleQuote: true,
tabWidth: 2,
trailingComma: 'es5',
};