From 030b23985d57dc23097a19b6a8dc71c43fe830ad Mon Sep 17 00:00:00 2001 From: Jared Palmer Date: Fri, 2 Jun 2023 11:15:04 -0400 Subject: [PATCH] Try to hack auth --- app/api/chat/route.ts | 43 ++ app/api/generate/route.ts | 45 --- app/chat-list.tsx | 2 +- app/chat.tsx | 32 +- app/chat/[id]/page.tsx | 2 +- app/sidebar.tsx | 12 +- app/use-prompt.tsx | 130 ------- auth.ts | 4 +- lib/db/db.ts | 4 - lib/db/index.ts | 38 +- ...s_moondragon.sql => 0000_clammy_freak.sql} | 8 +- lib/db/migrations/0001_colorful_spectrum.sql | 7 - lib/db/migrations/0001_petite_sue_storm.sql | 11 + lib/db/migrations/meta/0000_snapshot.json | 20 +- lib/db/migrations/meta/0001_snapshot.json | 122 +++--- lib/db/migrations/meta/_journal.json | 8 +- lib/db/schema.ts | 367 +++--------------- package.json | 10 +- pnpm-lock.yaml | 138 ++++--- 19 files changed, 330 insertions(+), 673 deletions(-) create mode 100644 app/api/chat/route.ts delete mode 100644 app/api/generate/route.ts delete mode 100644 app/use-prompt.tsx delete mode 100644 lib/db/db.ts rename lib/db/migrations/{0000_flawless_moondragon.sql => 0000_clammy_freak.sql} (93%) delete mode 100644 lib/db/migrations/0001_colorful_spectrum.sql create mode 100644 lib/db/migrations/0001_petite_sue_storm.sql diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts new file mode 100644 index 0000000..306db6e --- /dev/null +++ b/app/api/chat/route.ts @@ -0,0 +1,43 @@ +import { auth } from "@/auth"; +import { chats, db } from "@/lib/db/schema"; +import { openai } from "@/lib/openai"; +import { OpenAIStream, StreamingTextResponse } from "ai-connector"; + +export const runtime = "edge"; + +export const POST = auth(async function POST(req: Request) { + const json = await req.json(); + // @ts-ignore + console.log(req.auth); // todo fix types + + const res = await openai.createChatCompletion({ + model: "gpt-3.5-turbo", + messages: json.messages.map((m: any) => ({ + content: m.content, + role: m.role, + })), + temperature: 0.7, + top_p: 1, + frequency_penalty: 1, + max_tokens: 500, + n: 1, + stream: true, + }); + + const stream = await OpenAIStream(res, { + async onCompletion(completion) { + // @ts-ignore + if (req.auth?.user?.email == null) { + return; + } + const title = json.messages[0].content.substring(0, 20); + await db.insert(chats).values({ + id: crypto.randomUUID(), + title, + userId: (req as any).auth?.user?.email, + }); + }, + }); + + return new StreamingTextResponse(stream); +}); diff --git a/app/api/generate/route.ts b/app/api/generate/route.ts deleted file mode 100644 index 5d73c5a..0000000 --- a/app/api/generate/route.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { auth } from "@/auth"; -import { OpenAIStream, openai } from "@/lib/openai"; -import { prisma } from "@/lib/prisma"; - -export const POST = auth(async function POST(req: Request) { - const json = await req.json(); - // @ts-ignore - console.log(req.auth); // todo fix types - - const res = await openai.createChatCompletion({ - model: "gpt-3.5-turbo", - messages: json.messages, - temperature: 0.7, - top_p: 1, - frequency_penalty: 1, - max_tokens: 500, - n: 1, - stream: true, - }); - - const stream = await OpenAIStream(res); - - let fullResponse = ""; - const decoder = new TextDecoder(); - const saveToPrisma = new TransformStream({ - transform: async (chunk, controller) => { - controller.enqueue(chunk); - fullResponse += decoder.decode(chunk); - }, - flush: async () => { - await prisma.chat.upsert({ - where: { - id: json.id, - }, - create: json, - update: json, - }); - }, - }); - - return new Response(stream.pipeThrough(saveToPrisma), { - status: 200, - headers: { "Content-Type": "text/event-stream" }, - }); -}); diff --git a/app/chat-list.tsx b/app/chat-list.tsx index 22ddbc4..eac0318 100644 --- a/app/chat-list.tsx +++ b/app/chat-list.tsx @@ -1,6 +1,6 @@ "use client"; -import { type Message } from "@prisma/client"; +import { type Message } from "ai-connector"; import { ChatMessage } from "./chat-message"; import { NextChatLogo } from "@/components/ui/nextchat-logo"; diff --git a/app/chat.tsx b/app/chat.tsx index e3634b5..9d69ee5 100644 --- a/app/chat.tsx +++ b/app/chat.tsx @@ -4,39 +4,43 @@ import { type Message } from "@prisma/client"; import { useRouter } from "next/navigation"; import { ChatList } from "./chat-list"; import { Prompt } from "./prompt"; -import { usePrompt } from "./use-prompt"; +import { useChat } from "ai-connector"; export interface ChatProps { // create?: (input: string) => Chat | undefined; - messages?: Message[]; + initialMessages?: Message[]; id?: string; } export function Chat({ id, // create, - messages, + initialMessages, }: ChatProps) { const router = useRouter(); - const { isLoading, messageList, appendUserMessage, reloadLastMessage } = - usePrompt({ - messages, - id, - // onCreate: (id: string) => { - // router.push(`/chat/${id}`); - // }, - }); + const { isLoading, messages, reload, append } = useChat({ + initialMessages: initialMessages as any[], + id, + // onCreate: (id: string) => { + // router.push(`/chat/${id}`); + // }, + }); return (
- +
{ + append({ + content: value, + role: "user", + }); + }} + onRefresh={messages.length ? reload : undefined} isLoading={isLoading} />
diff --git a/app/chat/[id]/page.tsx b/app/chat/[id]/page.tsx index f4e6f06..51331ce 100644 --- a/app/chat/[id]/page.tsx +++ b/app/chat/[id]/page.tsx @@ -46,7 +46,7 @@ export default async function ChatPage({ params }: ChatPageProps) {
- +
); diff --git a/app/sidebar.tsx b/app/sidebar.tsx index d43cd82..ed61d7a 100644 --- a/app/sidebar.tsx +++ b/app/sidebar.tsx @@ -8,6 +8,7 @@ import { Plus } from "lucide-react"; import Link from "next/link"; import { unstable_cache } from "next/cache"; import { SidebarItem } from "./sidebar-item"; +import { db } from "@/lib/db/schema"; export interface SidebarProps { session?: Session; @@ -60,16 +61,7 @@ Sidebar.displayName = "Sidebar"; async function SidebarList({ session }: { session?: Session }) { const chats = await ( await unstable_cache( - () => - prisma.chat.findMany({ - where: { - // This is for debugging, need to add scope to the query later - // userId: session?.user.id, - }, - orderBy: { - updatedAt: "desc", - }, - }), + () => db.query.chats.findMany({}), // @ts-ignore [session?.user?.id || ""], { diff --git a/app/use-prompt.tsx b/app/use-prompt.tsx deleted file mode 100644 index 9bf0a11..0000000 --- a/app/use-prompt.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { useState, useCallback, useRef, useEffect } from "react"; -import { type Message } from "@prisma/client"; -import { nanoid } from "@/lib/utils"; - -export function usePrompt({ - messages = [], - id, -}: { - messages?: Message[]; - id: string | undefined; -}) { - const [isLoading, setIsLoading] = useState(false); - const [messageList, setMessageList] = useState(messages); - - const isLoadingRef = useRef(isLoading); - const messageListRef = useRef(messageList); - - useEffect(() => { - isLoadingRef.current = isLoading; - }, [isLoading]); - - useEffect(() => { - messageListRef.current = messageList; - }, [messageList]); - - const appendUserMessage = useCallback( - async (content: string | Message) => { - // Prevent multiple requests at once - if (isLoadingRef.current) return; - - const userMsg = - typeof content === "string" - ? ({ id: nanoid(10), role: "user", content } as Message) - : content; - const assMsg = { - id: nanoid(10), - role: "assistant", - content: "", - } as Message; - const messageListSnapshot = messageListRef.current; - - // Reset output - setIsLoading(true); - - try { - // Set user input immediately - setMessageList([...messageListSnapshot, userMsg]); - - // If streaming, we need to use fetchEventSource directly - const response = await fetch(`/api/generate`, { - method: "POST", - body: JSON.stringify({ - id: id || nanoid(10), - messages: [...messageListSnapshot, userMsg].map((m) => ({ - role: m.role, - content: m.content, - })), - }), - headers: { "Content-Type": "application/json" }, - }); - // This data is a ReadableStream - const data = response.body; - if (!data) { - return; - } - - const reader = data.getReader(); - const decoder = new TextDecoder(); - let done = false; - let accumulatedValue = ""; // Variable to accumulate chunks - - while (!done) { - const { value, done: doneReading } = await reader.read(); - done = doneReading; - const chunkValue = decoder.decode(value); - accumulatedValue += chunkValue; // Accumulate the chunk value - - // Check if the accumulated value contains the delimiter - const delimiter = "\n"; - const chunks = accumulatedValue.split(delimiter); - - // Process all chunks except the last one (which may be incomplete) - while (chunks.length > 1) { - const chunkToDispatch = chunks.shift(); // Get the first chunk - if (chunkToDispatch && chunkToDispatch.length > 0) { - const chunk = JSON.parse(chunkToDispatch); - assMsg.content += chunk; - setMessageList([...messageListSnapshot, userMsg, assMsg]); - } - } - - // The last chunk may be incomplete, so keep it in the accumulated value - accumulatedValue = chunks[0]; - } - - // Process any remaining accumulated value after the loop is done - if (accumulatedValue.length > 0) { - assMsg.content += accumulatedValue; - setMessageList([...messageListSnapshot, userMsg, assMsg]); - } - } finally { - setIsLoading(false); - } - }, - [id] - ); - - const reloadLastMessage = useCallback(async () => { - // Prevent multiple requests at once - if (isLoadingRef.current) return; - - const userMsg = messageListRef.current.at(-2); - const assMsg = messageListRef.current.at(-1); - - // Both should exist. - if (!userMsg || !assMsg) return; - - messageListRef.current = messageListRef.current.slice(0, -2); - setMessageList(messageListRef.current); - - await appendUserMessage(userMsg); - }, [appendUserMessage]); - - return { - messageList, - appendUserMessage, - reloadLastMessage, - isLoading, - }; -} diff --git a/auth.ts b/auth.ts index cab5ae5..16f9e09 100644 --- a/auth.ts +++ b/auth.ts @@ -9,14 +9,14 @@ import { sessions, verificationTokens, } from "./lib/db/schema"; -import { DrizzleAdapterPg } from "./lib/db"; +import { PgAdapter } from "./lib/db"; export const { handlers: { GET, POST }, auth, CSRF_experimental, } = NextAuth({ - adapter: DrizzleAdapterPg(db, { + adapter: PgAdapter(db, { accounts, users, sessions, diff --git a/lib/db/db.ts b/lib/db/db.ts deleted file mode 100644 index 066b295..0000000 --- a/lib/db/db.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { drizzle } from "drizzle-orm/vercel-postgres"; -import { sql } from "@vercel/postgres"; - -export const db = drizzle(sql); diff --git a/lib/db/index.ts b/lib/db/index.ts index c96d1c5..60dd07d 100644 --- a/lib/db/index.ts +++ b/lib/db/index.ts @@ -9,15 +9,14 @@ * ## Installation * * ```bash npm2yarn2pnpm - * npm install next-auth drizzle-orm @next-auth/drizzle-adapter + * npm install next-auth drizzle-orm @auth/drizzle-adapter * npm install drizzle-kit --save-dev * ``` * - * @module @next-auth/drizzle-adapter + * @module @auth/drizzle-adapter */ -import type { Adapter } from "@auth/nextjs/adapters"; +import type { Adapter } from "@auth/core/adapters"; import { and, eq } from "drizzle-orm"; -import { v4 as uuid } from "uuid"; import type { DbClient, Schema } from "./schema"; /** @@ -28,7 +27,7 @@ import type { DbClient, Schema } from "./schema"; * ```js title="pages/api/auth/[...nextauth].js" * import NextAuth from "next-auth" * import GoogleProvider from "next-auth/providers/google" - * import { DrizzleAdapter } from "@next-auth/drizzle-adapter" + * import { DrizzleAdapter } from "@auth/drizzle-adapter" * import { db } from "./db-schema" * * export default NextAuth({ @@ -109,7 +108,7 @@ import type { DbClient, Schema } from "./schema"; * ``` * **/ -export function DrizzleAdapterPg( +export function PgAdapter( client: DbClient, { users, sessions, verificationTokens, accounts }: Schema ): Adapter { @@ -117,7 +116,7 @@ export function DrizzleAdapterPg( createUser: async (data) => { return client .insert(users) - .values({ ...data, id: uuid() }) + .values({ ...data, id: crypto.randomUUID() as string }) .returning() .then((res) => res[0]); }, @@ -188,7 +187,7 @@ export function DrizzleAdapterPg( // Drizzle will return `null` for fields that are not defined. // However, the return type is expecting `undefined`. - const account: ReturnType = { + const account = { ...updatedAccount, access_token: updatedAccount.access_token ?? undefined, token_type: updatedAccount.token_type ?? undefined, @@ -202,20 +201,19 @@ export function DrizzleAdapterPg( return account; }, getUserByAccount: async (account) => { - const user = - (await client - .select() - .from(users) - .innerJoin( - accounts, - and( - eq(accounts.providerAccountId, account.providerAccountId), - eq(accounts.provider, account.provider) - ) + const dbAccount = await client + .select() + .from(accounts) + .where( + and( + eq(accounts.providerAccountId, account.providerAccountId), + eq(accounts.provider, account.provider) ) - .then((res) => res[0])) ?? null; + ) + .leftJoin(users, eq(accounts.userId, users.id)) + .then((res) => res[0]); - return user.users; + return dbAccount.users; }, deleteSession: async (sessionToken) => { await client diff --git a/lib/db/migrations/0000_flawless_moondragon.sql b/lib/db/migrations/0000_clammy_freak.sql similarity index 93% rename from lib/db/migrations/0000_flawless_moondragon.sql rename to lib/db/migrations/0000_clammy_freak.sql index e634f49..5aac3c8 100644 --- a/lib/db/migrations/0000_flawless_moondragon.sql +++ b/lib/db/migrations/0000_clammy_freak.sql @@ -15,23 +15,23 @@ CREATE TABLE IF NOT EXISTS "accounts" ( ALTER TABLE "accounts" ADD CONSTRAINT "accounts_provider_providerAccountId" PRIMARY KEY("provider","providerAccountId"); CREATE TABLE IF NOT EXISTS "sessions" ( - "sessionToken" text PRIMARY KEY NOT NULL, "userId" text NOT NULL, - "expires" timestamp NOT NULL + "sessionToken" text PRIMARY KEY NOT NULL, + "expires" integer NOT NULL ); CREATE TABLE IF NOT EXISTS "users" ( "id" text PRIMARY KEY NOT NULL, "name" text, "email" text NOT NULL, - "emailVerified" timestamp, + "emailVerified" integer, "image" text ); CREATE TABLE IF NOT EXISTS "verificationToken" ( "identifier" text NOT NULL, "token" text NOT NULL, - "expires" timestamp NOT NULL + "expires" integer NOT NULL ); --> statement-breakpoint ALTER TABLE "verificationToken" ADD CONSTRAINT "verificationToken_identifier_token" PRIMARY KEY("identifier","token"); diff --git a/lib/db/migrations/0001_colorful_spectrum.sql b/lib/db/migrations/0001_colorful_spectrum.sql deleted file mode 100644 index 5ff3ddb..0000000 --- a/lib/db/migrations/0001_colorful_spectrum.sql +++ /dev/null @@ -1,7 +0,0 @@ -ALTER TABLE "accounts" DROP CONSTRAINT "accounts_provider_providerAccountId"; -ALTER TABLE "verificationToken" DROP CONSTRAINT "verificationToken_identifier_token"; -CREATE UNIQUE INDEX IF NOT EXISTS "Account_provider_providerAccountId_key" ON "accounts" ("provider","providerAccountId"); -CREATE UNIQUE INDEX IF NOT EXISTS "Session_sessionToken_key" ON "sessions" ("sessionToken"); -CREATE UNIQUE INDEX IF NOT EXISTS "User_email_key" ON "users" ("email"); -CREATE UNIQUE INDEX IF NOT EXISTS "VerificationToken_identifier_token_key" ON "verificationToken" ("identifier","token"); -CREATE UNIQUE INDEX IF NOT EXISTS "VerificationToken_token_key" ON "verificationToken" ("token"); \ No newline at end of file diff --git a/lib/db/migrations/0001_petite_sue_storm.sql b/lib/db/migrations/0001_petite_sue_storm.sql new file mode 100644 index 0000000..506efe6 --- /dev/null +++ b/lib/db/migrations/0001_petite_sue_storm.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS "chats" ( + "id" text PRIMARY KEY NOT NULL, + "role" text NOT NULL, + "userId" text NOT NULL +); + +DO $$ BEGIN + ALTER TABLE "chats" ADD CONSTRAINT "chats_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/lib/db/migrations/meta/0000_snapshot.json b/lib/db/migrations/meta/0000_snapshot.json index 9bf3d1e..f0e3010 100644 --- a/lib/db/migrations/meta/0000_snapshot.json +++ b/lib/db/migrations/meta/0000_snapshot.json @@ -1,7 +1,7 @@ { "version": "5", "dialect": "pg", - "id": "ea430ef9-8e30-4cb6-9985-d03f43656cf8", + "id": "c6cb6121-2dc1-49be-8bd9-62f1c0c55939", "prevId": "00000000-0000-0000-0000-000000000000", "tables": { "accounts": { @@ -105,21 +105,21 @@ "name": "sessions", "schema": "", "columns": { - "sessionToken": { - "name": "sessionToken", - "type": "text", - "primaryKey": true, - "notNull": true - }, "userId": { "name": "userId", "type": "text", "primaryKey": false, "notNull": true }, + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, "expires": { "name": "expires", - "type": "timestamp", + "type": "integer", "primaryKey": false, "notNull": true } @@ -166,7 +166,7 @@ }, "emailVerified": { "name": "emailVerified", - "type": "timestamp", + "type": "integer", "primaryKey": false, "notNull": false }, @@ -199,7 +199,7 @@ }, "expires": { "name": "expires", - "type": "timestamp", + "type": "integer", "primaryKey": false, "notNull": true } diff --git a/lib/db/migrations/meta/0001_snapshot.json b/lib/db/migrations/meta/0001_snapshot.json index 9f8af6f..2042ae3 100644 --- a/lib/db/migrations/meta/0001_snapshot.json +++ b/lib/db/migrations/meta/0001_snapshot.json @@ -1,8 +1,8 @@ { "version": "5", "dialect": "pg", - "id": "34122d24-88e0-430e-862c-2168b0f866cb", - "prevId": "ea430ef9-8e30-4cb6-9985-d03f43656cf8", + "id": "ad52915b-d697-4935-9373-97dca163dd91", + "prevId": "c6cb6121-2dc1-49be-8bd9-62f1c0c55939", "tables": { "accounts": { "name": "accounts", @@ -75,16 +75,7 @@ "notNull": false } }, - "indexes": { - "Account_provider_providerAccountId_key": { - "name": "Account_provider_providerAccountId_key", - "columns": [ - "provider", - "providerAccountId" - ], - "isUnique": true - } - }, + "indexes": {}, "foreignKeys": { "accounts_userId_users_id_fk": { "name": "accounts_userId_users_id_fk", @@ -100,40 +91,81 @@ "onUpdate": "no action" } }, - "compositePrimaryKeys": {} + "compositePrimaryKeys": { + "accounts_provider_providerAccountId": { + "name": "accounts_provider_providerAccountId", + "columns": [ + "provider", + "providerAccountId" + ] + } + } }, - "sessions": { - "name": "sessions", + "chats": { + "name": "chats", "schema": "", "columns": { - "sessionToken": { - "name": "sessionToken", + "id": { + "name": "id", "type": "text", "primaryKey": true, "notNull": true }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, "userId": { "name": "userId", "type": "text", "primaryKey": false, "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "chats_userId_users_id_fk": { + "name": "chats_userId_users_id_fk", + "tableFrom": "chats", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true }, "expires": { "name": "expires", - "type": "timestamp", + "type": "integer", "primaryKey": false, "notNull": true } }, - "indexes": { - "Session_sessionToken_key": { - "name": "Session_sessionToken_key", - "columns": [ - "sessionToken" - ], - "isUnique": true - } - }, + "indexes": {}, "foreignKeys": { "sessions_userId_users_id_fk": { "name": "sessions_userId_users_id_fk", @@ -175,7 +207,7 @@ }, "emailVerified": { "name": "emailVerified", - "type": "timestamp", + "type": "integer", "primaryKey": false, "notNull": false }, @@ -186,15 +218,7 @@ "notNull": false } }, - "indexes": { - "User_email_key": { - "name": "User_email_key", - "columns": [ - "email" - ], - "isUnique": true - } - }, + "indexes": {}, "foreignKeys": {}, "compositePrimaryKeys": {} }, @@ -216,30 +240,22 @@ }, "expires": { "name": "expires", - "type": "timestamp", + "type": "integer", "primaryKey": false, "notNull": true } }, - "indexes": { - "VerificationToken_identifier_token_key": { - "name": "VerificationToken_identifier_token_key", + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verificationToken_identifier_token": { + "name": "verificationToken_identifier_token", "columns": [ "identifier", "token" - ], - "isUnique": true - }, - "VerificationToken_token_key": { - "name": "VerificationToken_token_key", - "columns": [ - "token" - ], - "isUnique": true + ] } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {} + } } }, "enums": {}, diff --git a/lib/db/migrations/meta/_journal.json b/lib/db/migrations/meta/_journal.json index c023d95..b5d790b 100644 --- a/lib/db/migrations/meta/_journal.json +++ b/lib/db/migrations/meta/_journal.json @@ -5,15 +5,15 @@ { "idx": 0, "version": "5", - "when": 1684771069602, - "tag": "0000_flawless_moondragon", + "when": 1685716228240, + "tag": "0000_clammy_freak", "breakpoints": false }, { "idx": 1, "version": "5", - "when": 1684771628481, - "tag": "0001_colorful_spectrum", + "when": 1685716937211, + "tag": "0001_petite_sue_storm", "breakpoints": false } ] diff --git a/lib/db/schema.ts b/lib/db/schema.ts index 44be2d6..015046d 100644 --- a/lib/db/schema.ts +++ b/lib/db/schema.ts @@ -1,28 +1,23 @@ -import { - integer, - timestamp, - pgTable, - text, - primaryKey, - uniqueIndex, -} from "drizzle-orm/pg-core"; -import { drizzle } from "drizzle-orm/vercel-postgres"; -import { sql } from "@vercel/postgres"; import { ProviderType } from "@auth/nextjs/providers"; +import { sql } from "@vercel/postgres"; +import { relations } from "drizzle-orm"; +import { integer, pgTable, primaryKey, text } from "drizzle-orm/pg-core"; +import { drizzle } from "drizzle-orm/vercel-postgres"; -export const users = pgTable( - "users", - { - id: text("id").notNull().primaryKey(), - name: text("name"), - email: text("email").notNull(), - emailVerified: timestamp("emailVerified", { mode: "date" }), - image: text("image"), - }, - (user) => ({ - emailKey: uniqueIndex("User_email_key").on(user.email), - }) -); +// const connection = createPool({ connectionString: process.env.POSTGRES_URL }); + +export const users = pgTable("users", { + id: text("id").notNull().primaryKey(), + name: text("name"), + email: text("email").notNull(), + emailVerified: integer("emailVerified"), + image: text("image"), +}); + +export const usersRelations = relations(users, ({ many }) => ({ + chats: many(chats), + accounts: many(accounts), +})); export const accounts = pgTable( "accounts", @@ -41,313 +36,63 @@ export const accounts = pgTable( id_token: text("id_token"), session_state: text("session_state"), }, - (table) => { - return { - providerProviderAccountIdKey: uniqueIndex( - "Account_provider_providerAccountId_key" - ).on(table.provider, table.providerAccountId), - }; - } + (account) => ({ + _: primaryKey(account.provider, account.providerAccountId), + }) ); -export const sessions = pgTable( - "sessions", - { - sessionToken: text("sessionToken").notNull().primaryKey(), - userId: text("userId") - .notNull() - .references(() => users.id, { onDelete: "cascade" }), - expires: timestamp("expires", { mode: "date" }).notNull(), - }, - (table) => { - return { - sessionTokenKey: uniqueIndex("Session_sessionToken_key").on( - table.sessionToken - ), - }; - } -); +export const sessions = pgTable("sessions", { + userId: text("userId") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + sessionToken: text("sessionToken").notNull().primaryKey(), + expires: integer("expires").notNull(), +}); export const verificationTokens = pgTable( "verificationToken", { identifier: text("identifier").notNull(), token: text("token").notNull(), - expires: timestamp("expires", { mode: "date" }).notNull(), + expires: integer("expires").notNull(), }, - (table) => ({ - identifierTokenKey: uniqueIndex( - "VerificationToken_identifier_token_key" - ).on(table.identifier, table.token), - tokenKey: uniqueIndex("VerificationToken_token_key").on(table.token), + (vt) => ({ + _: primaryKey(vt.identifier, vt.token), }) ); -// Connect to Vercel Postgres -export const db = drizzle(sql); - -export type DbClient = typeof db; - export type Schema = { users: typeof users; accounts: typeof accounts; sessions: typeof sessions; verificationTokens: typeof verificationTokens; }; -// import { sql, eq, and } from "drizzle-orm"; -// import { -// PgDatabase, -// QueryResultHKT, -// integer, -// pgTable, -// text, -// timestamp, -// uniqueIndex, -// uuid, -// } from "drizzle-orm/pg-core"; -// import { drizzle } from "drizzle-orm/vercel-postgres"; -// import { sql as c } from "@vercel/postgres"; -// import { Adapter, AdapterUser } from "@auth/nextjs/adapters"; -// export const db = drizzle(c); +export const chats = pgTable("chats", { + id: text("id").notNull().primaryKey(), + title: text("role").notNull(), + userId: text("userId") + .notNull() + .references(() => users.id), +}); -// export const users = pgTable( -// "users", -// { -// id: uuid("id") -// .notNull() -// .primaryKey() -// .default(sql`gen_random_uuid()`), -// name: text("name"), -// email: text("email"), -// emailVerified: timestamp("emailVerified", { precision: 3 }), -// image: text("image"), -// }, -// (table) => { -// return { -// emailKey: uniqueIndex("User_email_key").on(table.email), -// }; -// } -// ); +export const chatsRelations = relations(chats, ({ one }) => ({ + user: one(users, { + fields: [chats.userId], + references: [users.id], + }), +})); -// export const verificationTokens = pgTable( -// "verification_tokens", -// { -// identifier: text("identifier").notNull(), -// token: text("token").notNull(), -// expires: timestamp("expires", { precision: 3 }).notNull(), -// }, -// (table) => { -// return { -// identifierTokenKey: uniqueIndex( -// "VerificationToken_identifier_token_key" -// ).on(table.identifier, table.token), -// tokenKey: uniqueIndex("VerificationToken_token_key").on(table.token), -// }; -// } -// ); +export const db = drizzle(sql, { + schema: { + users, + accounts, + sessions, + verificationTokens, + chats, + chatsRelations, + usersRelations, + }, +}); -// export const sessions = pgTable( -// "sessions", -// { -// id: uuid("id") -// .notNull() -// .primaryKey() -// .default(sql`gen_random_uuid()`), -// sessionToken: text("sessionToken").notNull(), -// userId: uuid("userId") -// .notNull() -// .references(() => users.id, { onDelete: "cascade", onUpdate: "cascade" }), -// expires: timestamp("expires", { precision: 3 }).notNull(), -// }, -// (table) => { -// return { -// sessionTokenKey: uniqueIndex("Session_sessionToken_key").on( -// table.sessionToken -// ), -// }; -// } -// ); - -// export const accounts = pgTable( -// "accounts", -// { -// id: uuid("id") -// .notNull() -// .primaryKey() -// .default(sql`gen_random_uuid()`), -// userId: uuid("userId") -// .notNull() -// .references(() => users.id, { onDelete: "cascade", onUpdate: "cascade" }), -// type: text("type").notNull(), -// provider: text("provider").notNull(), -// providerAccountId: text("providerAccountId").notNull(), -// refresh_token: text("refresh_token"), -// access_token: text("access_token"), -// expires_at: integer("expires_at"), -// token_type: text("token_type"), -// scope: text("scope"), -// id_token: text("id_token"), -// session_state: text("session_state"), -// }, -// (table) => { -// return { -// providerProviderAccountIdKey: uniqueIndex( -// "Account_provider_providerAccountId_key" -// ).on(table.provider, table.providerAccountId), -// }; -// } -// ); - -// type Users = typeof users; -// type Sessions = typeof sessions; -// type Accounts = typeof accounts; -// type VerificationTokens = typeof verificationTokens; - -// export function DrizzleAdapter< -// T extends PgDatabase, -// U extends QueryResultHKT -// >({ -// db, -// schema, -// }: { -// db: T; -// schema: { -// users: Users; -// sessions: Sessions; -// accounts: Accounts; -// verificationTokens: VerificationTokens; -// }; -// }): Adapter { -// return { -// async createUser(user) { -// const [newUser] = await db.insert(schema.users).values(user).returning(); - -// return newUser as AdapterUser; -// }, -// async getUser(id) { -// const [user] = await db -// .select() -// .from(schema.users) -// .where(eq(schema.users.id, id)); - -// return (user as AdapterUser) || null; -// }, -// async getUserByEmail(email) { -// const [user] = await db -// .select() -// .from(schema.users) -// .where(eq(schema.users.email, email)); - -// return (user as AdapterUser) || null; -// }, -// async getUserByAccount({ providerAccountId, provider }) { -// const results = await db -// .select() -// .from(schema.users) -// .leftJoin(schema.accounts, eq(schema.accounts.userId, schema.users.id)) -// .where( -// and( -// eq(schema.accounts.provider, provider), -// eq(schema.accounts.providerAccountId, providerAccountId) -// ) -// ); - -// if (results.length) { -// return results[0].users as AdapterUser; -// } - -// return null; -// }, -// async updateUser(user) { -// const userId = user.id; - -// if (!userId) { -// throw new Error("Cannot update user without id"); -// } - -// const [updatedUser] = await db -// .update(schema.users) -// .set(user) -// .where(eq(schema.users.id, userId)) -// .returning(); - -// return updatedUser as AdapterUser; -// }, -// async deleteUser(userId) { -// await db.delete(schema.users).where(eq(schema.users.id, userId)); -// }, -// async linkAccount(account) { -// await db.insert(schema.accounts).values(account); -// }, -// async unlinkAccount({ providerAccountId, provider }) { -// await db -// .delete(schema.accounts) -// .where( -// and( -// eq(schema.accounts.provider, provider), -// eq(schema.accounts.providerAccountId, providerAccountId) -// ) -// ); -// }, -// async createSession(session) { -// const [newSession] = await db -// .insert(schema.sessions) -// .values(session) -// .returning(); - -// return newSession; -// }, -// async getSessionAndUser(sessionToken) { -// const results = await db -// .select() -// .from(schema.sessions) -// .leftJoin(schema.users, eq(schema.users.id, schema.sessions.userId)) -// .where(eq(schema.sessions.sessionToken, sessionToken)); - -// if (results.length) { -// return { -// user: results[0].users! as AdapterUser, -// session: results[0].sessions, -// }; -// } - -// return null; -// }, -// async updateSession(session) { -// const [updatedSession] = await db -// .update(schema.sessions) -// .set(session) -// .where(eq(schema.sessions.sessionToken, session.sessionToken)) -// .returning(); - -// return updatedSession; -// }, -// async deleteSession(sessionToken) { -// await db -// .delete(schema.sessions) -// .where(eq(schema.sessions.sessionToken, sessionToken)); -// }, -// async createVerificationToken(token) { -// const [newVerificationToken] = await db -// .insert(schema.verificationTokens) -// .values(token) -// .returning(); - -// return newVerificationToken; -// }, -// async useVerificationToken({ identifier, token }) { -// const [deletedVerificationToken] = await db -// .delete(schema.verificationTokens) -// .where( -// and( -// eq(schema.verificationTokens.identifier, identifier), -// eq(schema.verificationTokens.token, token) -// ) -// ) -// .returning(); - -// return deletedVerificationToken || null; -// }, -// }; -// } +export type DbClient = typeof db; diff --git a/package.json b/package.json index 640b8e5..ab8a553 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "version": "0.0.2", "private": true, "scripts": { - "dev": "prisma generate && next dev", - "build": "prisma generate && next build", + "dev": "next dev", + "build": "next build", "db:mg:create": "drizzle-kit generate:pg --config=drizzle.config.ts", "db:mg:apply": "ts-node --project tsconfig.migration.json ./lib/db/migrate --config=drizzle.config.ts", "db:check": "drizzle-kit check:pg --config=drizzle.config.ts", @@ -18,6 +18,7 @@ "format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache" }, "dependencies": { + "@auth/core": "0.0.0-manual.527fff6c", "@auth/nextjs": "0.0.0-manual.030e8328", "@next-auth/prisma-adapter": "1.0.6", "@prisma/client": "^4.14.0", @@ -25,6 +26,7 @@ "@vercel/analytics": "^1.0.0", "@vercel/kv": "^0.2.1", "@vercel/postgres": "^0.3.0", + "ai-connector": "^0.0.5", "body-scroll-lock": "4.0.0-beta.0", "class-variance-authority": "^0.4.0", "clsx": "^1.2.1", @@ -38,7 +40,7 @@ "jsonwebtoken": "^9.0.0", "lucide-react": "0.216.0", "nanoid": "^4.0.2", - "next": "13.4.3-canary.3", + "next": "13.4.5-canary.3", "next-themes": "^0.2.1", "openai-edge": "^0.5.1", "react": "^18.2.0", @@ -69,7 +71,7 @@ "dotenv": "^16.0.3", "drizzle-kit": "^0.18.0", "eslint": "^8.31.0", - "eslint-config-next": "13.4.3-canary.3", + "eslint-config-next": "13.4.5-canary.3", "eslint-config-prettier": "^8.3.0", "eslint-plugin-react": "^7.31.11", "eslint-plugin-tailwindcss": "^3.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ee82ff..0797cd1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,9 +4,12 @@ overrides: '@auth/core': 0.0.0-manual.527fff6c dependencies: + '@auth/core': + specifier: 0.0.0-manual.527fff6c + version: 0.0.0-manual.527fff6c '@auth/nextjs': specifier: 0.0.0-manual.030e8328 - version: 0.0.0-manual.030e8328(next@13.4.3-canary.3)(react@18.2.0) + version: 0.0.0-manual.030e8328(next@13.4.5-canary.3)(react@18.2.0) '@next-auth/prisma-adapter': specifier: 1.0.6 version: 1.0.6(@prisma/client@4.14.0)(next-auth@4.22.1) @@ -25,6 +28,9 @@ dependencies: '@vercel/postgres': specifier: ^0.3.0 version: 0.3.0 + ai-connector: + specifier: ^0.0.5 + version: 0.0.5(react@18.2.0) body-scroll-lock: specifier: 4.0.0-beta.0 version: 4.0.0-beta.0 @@ -65,11 +71,11 @@ dependencies: specifier: ^4.0.2 version: 4.0.2 next: - specifier: 13.4.3-canary.3 - version: 13.4.3-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) + specifier: 13.4.5-canary.3 + version: 13.4.5-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@13.4.3-canary.3)(react-dom@18.2.0)(react@18.2.0) + version: 0.2.1(next@13.4.5-canary.3)(react-dom@18.2.0)(react@18.2.0) openai-edge: specifier: ^0.5.1 version: 0.5.1 @@ -154,8 +160,8 @@ devDependencies: specifier: ^8.31.0 version: 8.40.0 eslint-config-next: - specifier: 13.4.3-canary.3 - version: 13.4.3-canary.3(eslint@8.40.0)(typescript@4.9.5) + specifier: 13.4.5-canary.3 + version: 13.4.5-canary.3(eslint@8.40.0)(typescript@4.9.5) eslint-config-prettier: specifier: ^8.3.0 version: 8.8.0(eslint@8.40.0) @@ -213,14 +219,14 @@ packages: preact-render-to-string: 5.2.3(preact@10.11.3) dev: false - /@auth/nextjs@0.0.0-manual.030e8328(next@13.4.3-canary.3)(react@18.2.0): + /@auth/nextjs@0.0.0-manual.030e8328(next@13.4.5-canary.3)(react@18.2.0): resolution: {integrity: sha512-AAtUl9EVCKqLRneDAq6KfUprWmsBRzsBoQ+8ytz/Nfgs8Uax5CWvCJs2CsnYNk04bXSB4L7eyMJmc1zTzZKaHg==} peerDependencies: next: ^13.4.2 react: ^18.2.0 dependencies: '@auth/core': 0.0.0-manual.527fff6c - next: 13.4.3-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) + next: 13.4.5-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 transitivePeerDependencies: - nodemailer @@ -593,21 +599,21 @@ packages: next-auth: ^4 dependencies: '@prisma/client': 4.14.0(prisma@4.14.0) - next-auth: 4.22.1(next@13.4.3-canary.3)(react-dom@18.2.0)(react@18.2.0) + next-auth: 4.22.1(next@13.4.5-canary.3)(react-dom@18.2.0)(react@18.2.0) dev: false - /@next/env@13.4.3-canary.3: - resolution: {integrity: sha512-AlAPQdQ2qf3RJsaaKMXo22l9MLUeqIiDJSJ1LcM9uWiOMIAgsLlQCxcoGcm7rQP9CSw4VPPFSpCR0tvCKmxVwQ==} + /@next/env@13.4.5-canary.3: + resolution: {integrity: sha512-2TrPvCIs8R9DpFpEDmGUOpWkVqbpb4+sGQMcZVP4zDYYg893p0nAbNbBxL996oBl+/vLTzcLIDceP5peHsGPzg==} dev: false - /@next/eslint-plugin-next@13.4.3-canary.3: - resolution: {integrity: sha512-ggD4Z0psyVcLcr0QlGXu+zEdbiYZra8r9LZgL1XuTAtTl4H1h3QgpNB6ENVqJCQibH8h0bBktOrRpHiLwbyRQw==} + /@next/eslint-plugin-next@13.4.5-canary.3: + resolution: {integrity: sha512-hsFfLSo8snWDLBwDT7+i4gEWZjsEzNHlZLT0ox8ftcZo3XBz8FrX11h9yGacageRbiiTotl/5U31Dxrt7MVoBA==} dependencies: glob: 7.1.7 dev: true - /@next/swc-darwin-arm64@13.4.3-canary.3: - resolution: {integrity: sha512-MVmNJTKe50Qm5a6Khju3MpYiTie9ByJVT67rvYxCfZkd48p59PWoosu9tvCtlVuxb5jZxzOAZ/vzDciTs7Vgcw==} + /@next/swc-darwin-arm64@13.4.5-canary.3: + resolution: {integrity: sha512-mUlpzua0RDPLNfNeqi0DzWNCqVzMphNh42BS8PojVO3NPC55+RX9tllQngz+qFAOcLL7g4LgoeE9VWgh31s/WQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -615,8 +621,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@13.4.3-canary.3: - resolution: {integrity: sha512-NLrVHpJNqrKF93gZEQSoEq1WAVy0JYq8fry7CvSj2cCjgQxna06LPfkX9R3Iu3eRJJD/idCxbedXjg52oma/sg==} + /@next/swc-darwin-x64@13.4.5-canary.3: + resolution: {integrity: sha512-0bkYuSFh1/0ZedCVsSMtHiSxdfQxF0BO/v5VwRdOLtOZE8WrQdoXsWiVsiFBOTutiZDhats9exFOFgmymoSqSA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -624,8 +630,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@13.4.3-canary.3: - resolution: {integrity: sha512-CfrQFtHsbSeN43o/OSMCSUmA610u3gteKhq1SGzzq7TVaT4OnqoHEHfROEmgrpAkIMq65yIlHJM/Aq3/EBkFaw==} + /@next/swc-linux-arm64-gnu@13.4.5-canary.3: + resolution: {integrity: sha512-+PxhM2E98APKNEl1FCwhqU9ttGRoWsZcPPU20qcKFrJ/fKbfaWDnhzlSiZPmmERISZrmd54Uy3maNq9ys+bz6g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -633,8 +639,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@13.4.3-canary.3: - resolution: {integrity: sha512-rRAilp0kqBAWJJuOfaK+GFclricB/lqFspFhk7U6tkYDHyXDZ/MrjTlfOraOJtqBTFtLM1zuzLvPhcK22DzJhA==} + /@next/swc-linux-arm64-musl@13.4.5-canary.3: + resolution: {integrity: sha512-KMRWPxeoZ41146NHpMAGMtD/RkQt/0QOlL13pREnNjeTzQI6P20X+ra5tHkCQoFB/8xseN9RXnuLMyYG3mYoGw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -642,8 +648,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@13.4.3-canary.3: - resolution: {integrity: sha512-9weSKDC6eJcDOhKURj/oKa7f9Z9fEZKjnYQBJDX/ojy1LThei/drRNXYrXTY1iay7tcbRhEBvtCiYaEPjvLBUA==} + /@next/swc-linux-x64-gnu@13.4.5-canary.3: + resolution: {integrity: sha512-dwSxDddWMaTAmSPxSWWrwaHHPqLlnNJoc22dTfyQX9Hwecq+Sq2RGSkGicga3z6Z7rX3Nm4MbNduM2GWXwcvgg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -651,8 +657,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@13.4.3-canary.3: - resolution: {integrity: sha512-yODhVd1qvxFhUja4WrSJhZhyiLD85O5855FxCVxky85qb2+aTjWMYv5DM7sl1fzCag7EwtcI4+HJb4rkBMifRQ==} + /@next/swc-linux-x64-musl@13.4.5-canary.3: + resolution: {integrity: sha512-R2SqJsC6QPNxO3t/U2fMouzLfUNLHP8PfZH/XTIwQ12dxZCwUwBg/cNX5ocBtoci3lCYNcOLNjSuc3z9b/yIeQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -660,8 +666,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@13.4.3-canary.3: - resolution: {integrity: sha512-2SY5f5tndZtObiqS2Uioyou18Ef+fG5yzCj4EAvk1FhuQBoprLaVDyP3wehJACg9U5kYocvLA18wKIt8byhG2g==} + /@next/swc-win32-arm64-msvc@13.4.5-canary.3: + resolution: {integrity: sha512-/spv7kDp2xKUJzdvGFU2gf/N1lXtm/E2p/Fx/XreUyajiaT0f57d2mHfDabW5saq3KL3wPlWZ5zW7iDh2Awm+Q==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -669,8 +675,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@13.4.3-canary.3: - resolution: {integrity: sha512-eCEPIrSkpIG+k4h9d8h56lVhqpPjjFm/C/P3Vq1AGDSPh9DQ+xfWTleWBeVskKO4RZf1R4aCHLVw12rkQcLw8g==} + /@next/swc-win32-ia32-msvc@13.4.5-canary.3: + resolution: {integrity: sha512-VIlQ+emO306CYbIyEKu8RTAzmMw/z+akEhu2urZPKjj+UMKCLfq1w4u3GJfURfdRiJ5ws7fLXDHVAjon4G+Ygg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -678,8 +684,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@13.4.3-canary.3: - resolution: {integrity: sha512-n8vAEOOiFgbXleiPTAQjiEgMFCLQaTqPl23fmzf/yKx2RjmWxYM19vn7SoaV20sVPK36KMAorxxYB7H/ny9hKw==} + /@next/swc-win32-x64-msvc@13.4.5-canary.3: + resolution: {integrity: sha512-JSb5haHmRxn2Jysrsw3UJ/mgNu0TD+JJdHyGkdQeGIM4V1Q1G/KgQNCTovWfimd8e1JUoZqSV4aX+y7zEDVkEg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1284,6 +1290,18 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + /ai-connector@0.0.5(react@18.2.0): + resolution: {integrity: sha512-byHDAVQt3zlQ61uEBDKlOlY3uX2O+ahNVV1bnnHhnv4fNIlu+NWefxlRUqAxVM80tlCrS/+aXA8AlpkIZsa1tg==} + engines: {node: '>=14.6'} + peerDependencies: + react: ^18.0.0 + dependencies: + eventsource-parser: 1.0.0 + nanoid: 3.3.6 + react: 18.2.0 + swr: 2.1.5(react@18.2.0) + dev: false + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -2313,8 +2331,8 @@ packages: engines: {node: '>=12'} dev: false - /eslint-config-next@13.4.3-canary.3(eslint@8.40.0)(typescript@4.9.5): - resolution: {integrity: sha512-vKWwNIUvCRRZLHejVAu/eodOMRmTVYHsTnzFIAQeD7PEIbyJl8fTntPyoE3rPgChWamRYAWR9isyZER4ToUc7Q==} + /eslint-config-next@13.4.5-canary.3(eslint@8.40.0)(typescript@4.9.5): + resolution: {integrity: sha512-F1W76ozmRCPk8sxPXO4tSy3pstBerEfiZ1Aiagr+d2a+l/Mx5CgHWf75CwsQfpiC6BbAee8RrdIjb8kvGlPeww==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -2322,7 +2340,7 @@ packages: typescript: optional: true dependencies: - '@next/eslint-plugin-next': 13.4.3-canary.3 + '@next/eslint-plugin-next': 13.4.5-canary.3 '@rushstack/eslint-patch': 1.2.0 '@typescript-eslint/parser': 5.59.5(eslint@8.40.0)(typescript@4.9.5) eslint: 8.40.0 @@ -4031,7 +4049,7 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /next-auth@4.22.1(next@13.4.3-canary.3)(react-dom@18.2.0)(react@18.2.0): + /next-auth@4.22.1(next@13.4.5-canary.3)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-NTR3f6W7/AWXKw8GSsgSyQcDW6jkslZLH8AiZa5PQ09w1kR8uHtR9rez/E9gAq/o17+p0JYHE8QjF3RoniiObA==} peerDependencies: next: ^12.2.5 || ^13 @@ -4046,7 +4064,7 @@ packages: '@panva/hkdf': 1.1.1 cookie: 0.5.0 jose: 4.14.4 - next: 13.4.3-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) + next: 13.4.5-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) oauth: 0.9.15 openid-client: 5.4.2 preact: 10.14.1 @@ -4056,14 +4074,14 @@ packages: uuid: 8.3.2 dev: false - /next-themes@0.2.1(next@13.4.3-canary.3)(react-dom@18.2.0)(react@18.2.0): + /next-themes@0.2.1(next@13.4.5-canary.3)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} peerDependencies: next: '*' react: '*' react-dom: '*' dependencies: - next: 13.4.3-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) + next: 13.4.5-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -4072,14 +4090,13 @@ packages: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: true - /next@13.4.3-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-Fix/RAVHJHUpJZsvftaC5Pm8qGP7/NIitOBsKPozSPKIekCUWwKiaoLPY140taMgl9R+oW1nXKwYhAdjM8gSMg==} + /next@13.4.5-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5YLpHWSLjjInYlqxtkZZr7cwYp62wXEm7ik6Wu+4JqWQdbwD/pemuXwErxRIt65ruDQwe9RvE/dzMOuQuNDE+A==} engines: {node: '>=16.8.0'} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 fibers: '>= 3.1.0' - node-sass: ^6.0.0 || ^7.0.0 react: ^18.2.0 react-dom: ^18.2.0 sass: ^1.3.0 @@ -4088,12 +4105,10 @@ packages: optional: true fibers: optional: true - node-sass: - optional: true sass: optional: true dependencies: - '@next/env': 13.4.3-canary.3 + '@next/env': 13.4.5-canary.3 '@swc/helpers': 0.5.1 busboy: 1.6.0 caniuse-lite: 1.0.30001486 @@ -4103,15 +4118,15 @@ packages: styled-jsx: 5.1.1(@babel/core@7.21.8)(react@18.2.0) zod: 3.21.4 optionalDependencies: - '@next/swc-darwin-arm64': 13.4.3-canary.3 - '@next/swc-darwin-x64': 13.4.3-canary.3 - '@next/swc-linux-arm64-gnu': 13.4.3-canary.3 - '@next/swc-linux-arm64-musl': 13.4.3-canary.3 - '@next/swc-linux-x64-gnu': 13.4.3-canary.3 - '@next/swc-linux-x64-musl': 13.4.3-canary.3 - '@next/swc-win32-arm64-msvc': 13.4.3-canary.3 - '@next/swc-win32-ia32-msvc': 13.4.3-canary.3 - '@next/swc-win32-x64-msvc': 13.4.3-canary.3 + '@next/swc-darwin-arm64': 13.4.5-canary.3 + '@next/swc-darwin-x64': 13.4.5-canary.3 + '@next/swc-linux-arm64-gnu': 13.4.5-canary.3 + '@next/swc-linux-arm64-musl': 13.4.5-canary.3 + '@next/swc-linux-x64-gnu': 13.4.5-canary.3 + '@next/swc-linux-x64-musl': 13.4.5-canary.3 + '@next/swc-win32-arm64-msvc': 13.4.5-canary.3 + '@next/swc-win32-ia32-msvc': 13.4.5-canary.3 + '@next/swc-win32-x64-msvc': 13.4.5-canary.3 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -5059,6 +5074,15 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + /swr@2.1.5(react@18.2.0): + resolution: {integrity: sha512-/OhfZMcEpuz77KavXST5q6XE9nrOBOVcBLWjMT+oAE/kQHyE3PASrevXCtQDZ8aamntOfFkbVJp7Il9tNBQWrw==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + /synckit@0.8.5: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} engines: {node: ^14.18.0 || >=16.0.0} @@ -5405,6 +5429,14 @@ packages: tslib: 2.5.0 dev: false + /use-sync-external-store@1.2.0(react@18.2.0): + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + /utf-8-validate@6.0.3: resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==} engines: {node: '>=6.14.2'}