diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 306db6e..10c8031 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,6 +1,7 @@ import { auth } from "@/auth"; import { chats, db } from "@/lib/db/schema"; import { openai } from "@/lib/openai"; +import { nanoid } from "@/lib/utils"; import { OpenAIStream, StreamingTextResponse } from "ai-connector"; export const runtime = "edge"; @@ -31,11 +32,24 @@ export const POST = auth(async function POST(req: Request) { return; } const title = json.messages[0].content.substring(0, 20); - await db.insert(chats).values({ - id: crypto.randomUUID(), + const payload = { + id: json.id ?? crypto.randomUUID(), title, userId: (req as any).auth?.user?.email, - }); + messages: json.messages.concat({ + content: completion, + role: "assistant", + id: nanoid(), + }), + }; + await db + .insert(chats) + .values(payload) + .onConflictDoUpdate({ + target: json.id, + set: payload, + }) + .execute(); }, }); diff --git a/auth.ts b/auth.ts index 16f9e09..a123564 100644 --- a/auth.ts +++ b/auth.ts @@ -2,13 +2,6 @@ import NextAuth from "@auth/nextjs"; import GitHub from "@auth/nextjs/providers/github"; import { NextResponse } from "next/server"; -import { - db, - users, - accounts, - sessions, - verificationTokens, -} from "./lib/db/schema"; import { PgAdapter } from "./lib/db"; export const { @@ -16,12 +9,12 @@ export const { auth, CSRF_experimental, } = NextAuth({ - adapter: PgAdapter(db, { - accounts, - users, - sessions, - verificationTokens, - }), + // adapter: PgAdapter(db, { + // accounts, + // users, + // sessions, + // verificationTokens, + // }), // @ts-ignore providers: [GitHub], session: { strategy: "jwt" }, diff --git a/lib/db/migrations/0000_clammy_freak.sql b/lib/db/migrations/0000_clammy_freak.sql deleted file mode 100644 index 5aac3c8..0000000 --- a/lib/db/migrations/0000_clammy_freak.sql +++ /dev/null @@ -1,49 +0,0 @@ -CREATE TABLE IF NOT EXISTS "accounts" ( - "userId" text NOT NULL, - "type" text NOT NULL, - "provider" text NOT NULL, - "providerAccountId" text NOT NULL, - "refresh_token" text, - "access_token" text, - "expires_at" integer, - "token_type" text, - "scope" text, - "id_token" text, - "session_state" text -); ---> statement-breakpoint -ALTER TABLE "accounts" ADD CONSTRAINT "accounts_provider_providerAccountId" PRIMARY KEY("provider","providerAccountId"); - -CREATE TABLE IF NOT EXISTS "sessions" ( - "userId" text 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" integer, - "image" text -); - -CREATE TABLE IF NOT EXISTS "verificationToken" ( - "identifier" text NOT NULL, - "token" text NOT NULL, - "expires" integer NOT NULL -); ---> statement-breakpoint -ALTER TABLE "verificationToken" ADD CONSTRAINT "verificationToken_identifier_token" PRIMARY KEY("identifier","token"); - -DO $$ BEGIN - ALTER TABLE "accounts" ADD CONSTRAINT "accounts_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; - -DO $$ BEGIN - ALTER TABLE "sessions" ADD CONSTRAINT "sessions_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; diff --git a/lib/db/migrations/0000_fair_groot.sql b/lib/db/migrations/0000_fair_groot.sql new file mode 100644 index 0000000..efc8875 --- /dev/null +++ b/lib/db/migrations/0000_fair_groot.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS "chats" ( + "id" text PRIMARY KEY NOT NULL, + "role" text NOT NULL, + "userId" text NOT NULL, + "messages" json DEFAULT '{}'::json NOT NULL +); diff --git a/lib/db/migrations/0001_naive_gunslinger.sql b/lib/db/migrations/0001_naive_gunslinger.sql new file mode 100644 index 0000000..9a2c74b --- /dev/null +++ b/lib/db/migrations/0001_naive_gunslinger.sql @@ -0,0 +1 @@ +ALTER TABLE "chats" DROP COLUMN IF EXISTS "messages"; \ 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 deleted file mode 100644 index 506efe6..0000000 --- a/lib/db/migrations/0001_petite_sue_storm.sql +++ /dev/null @@ -1,11 +0,0 @@ -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 f0e3010..96a82fc 100644 --- a/lib/db/migrations/meta/0000_snapshot.json +++ b/lib/db/migrations/meta/0000_snapshot.json @@ -1,149 +1,11 @@ { "version": "5", "dialect": "pg", - "id": "c6cb6121-2dc1-49be-8bd9-62f1c0c55939", + "id": "3bddf21a-46a3-4ee8-8b41-bb79cb80d904", "prevId": "00000000-0000-0000-0000-000000000000", "tables": { - "accounts": { - "name": "accounts", - "schema": "", - "columns": { - "userId": { - "name": "userId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider": { - "name": "provider", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "providerAccountId": { - "name": "providerAccountId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "token_type": { - "name": "token_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "session_state": { - "name": "session_state", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "accounts_userId_users_id_fk": { - "name": "accounts_userId_users_id_fk", - "tableFrom": "accounts", - "tableTo": "users", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "accounts_provider_providerAccountId": { - "name": "accounts_provider_providerAccountId", - "columns": [ - "provider", - "providerAccountId" - ] - } - } - }, - "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": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "sessions_userId_users_id_fk": { - "name": "sessions_userId_users_id_fk", - "tableFrom": "sessions", - "tableTo": "users", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {} - }, - "users": { - "name": "users", + "chats": { + "name": "chats", "schema": "", "columns": { "id": { @@ -152,69 +14,29 @@ "primaryKey": true, "notNull": true }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", + "role": { + "name": "role", "type": "text", "primaryKey": false, "notNull": true }, - "emailVerified": { - "name": "emailVerified", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "image": { - "name": "image", + "userId": { + "name": "userId", "type": "text", "primaryKey": false, - "notNull": false + "notNull": true + }, + "messages": { + "name": "messages", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'::json" } }, "indexes": {}, "foreignKeys": {}, "compositePrimaryKeys": {} - }, - "verificationToken": { - "name": "verificationToken", - "schema": "", - "columns": { - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires": { - "name": "expires", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": { - "verificationToken_identifier_token": { - "name": "verificationToken_identifier_token", - "columns": [ - "identifier", - "token" - ] - } - } } }, "enums": {}, diff --git a/lib/db/migrations/meta/0001_snapshot.json b/lib/db/migrations/meta/0001_snapshot.json index 2042ae3..216b8d3 100644 --- a/lib/db/migrations/meta/0001_snapshot.json +++ b/lib/db/migrations/meta/0001_snapshot.json @@ -1,106 +1,9 @@ { "version": "5", "dialect": "pg", - "id": "ad52915b-d697-4935-9373-97dca163dd91", - "prevId": "c6cb6121-2dc1-49be-8bd9-62f1c0c55939", + "id": "e8eef642-fc25-4737-8e75-5ad1e8c53b84", + "prevId": "3bddf21a-46a3-4ee8-8b41-bb79cb80d904", "tables": { - "accounts": { - "name": "accounts", - "schema": "", - "columns": { - "userId": { - "name": "userId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider": { - "name": "provider", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "providerAccountId": { - "name": "providerAccountId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "token_type": { - "name": "token_type", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "session_state": { - "name": "session_state", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "accounts_userId_users_id_fk": { - "name": "accounts_userId_users_id_fk", - "tableFrom": "accounts", - "tableTo": "users", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": { - "accounts_provider_providerAccountId": { - "name": "accounts_provider_providerAccountId", - "columns": [ - "provider", - "providerAccountId" - ] - } - } - }, "chats": { "name": "chats", "schema": "", @@ -125,137 +28,8 @@ } }, "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": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "sessions_userId_users_id_fk": { - "name": "sessions_userId_users_id_fk", - "tableFrom": "sessions", - "tableTo": "users", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {} - }, - "users": { - "name": "users", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "emailVerified": { - "name": "emailVerified", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, "foreignKeys": {}, "compositePrimaryKeys": {} - }, - "verificationToken": { - "name": "verificationToken", - "schema": "", - "columns": { - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires": { - "name": "expires", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": { - "verificationToken_identifier_token": { - "name": "verificationToken_identifier_token", - "columns": [ - "identifier", - "token" - ] - } - } } }, "enums": {}, diff --git a/lib/db/migrations/meta/_journal.json b/lib/db/migrations/meta/_journal.json index b5d790b..d83e0fb 100644 --- a/lib/db/migrations/meta/_journal.json +++ b/lib/db/migrations/meta/_journal.json @@ -5,15 +5,15 @@ { "idx": 0, "version": "5", - "when": 1685716228240, - "tag": "0000_clammy_freak", + "when": 1685719783900, + "tag": "0000_fair_groot", "breakpoints": false }, { "idx": 1, "version": "5", - "when": 1685716937211, - "tag": "0001_petite_sue_storm", + "when": 1685719963202, + "tag": "0001_naive_gunslinger", "breakpoints": false } ] diff --git a/lib/db/schema.ts b/lib/db/schema.ts index 015046d..7f983f5 100644 --- a/lib/db/schema.ts +++ b/lib/db/schema.ts @@ -1,98 +1,56 @@ -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 { pgTable, text } from "drizzle-orm/pg-core"; import { drizzle } from "drizzle-orm/vercel-postgres"; // 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", - { - userId: text("userId") - .notNull() - .references(() => users.id, { onDelete: "cascade" }), - type: text("type").$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"), - }, - (account) => ({ - _: primaryKey(account.provider, account.providerAccountId), - }) -); - -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: integer("expires").notNull(), - }, - (vt) => ({ - _: primaryKey(vt.identifier, vt.token), - }) -); - -export type Schema = { - users: typeof users; - accounts: typeof accounts; - sessions: typeof sessions; - verificationTokens: typeof verificationTokens; -}; - export const chats = pgTable("chats", { id: text("id").notNull().primaryKey(), title: text("role").notNull(), - userId: text("userId") - .notNull() - .references(() => users.id), + userId: text("userId").notNull(), + // messages: json("messages").notNull().default({}), + // .references(() => users.id), }); -export const chatsRelations = relations(chats, ({ one }) => ({ - user: one(users, { - fields: [chats.userId], - references: [users.id], - }), -})); +// export const messages = pgTable("messages", { +// id: text("id").notNull().primaryKey(), +// title: text("role").notNull(), +// chatId: text("chatId") +// .notNull() +// .references(() => chats.id), +// }); + +// export const chatsRelations = relations(chats, ({ many }) => ({ +// // user: one(users, { +// // fields: [chats.userId], +// // references: [users.id], +// // }), +// messages: many(messages), +// })); + +// export const messagesRelations = relations(messages, ({ one }) => ({ +// chat: one(chats, { +// fields: [messages.chatId], +// references: [chats.id], +// }), +// })); export const db = drizzle(sql, { schema: { - users, - accounts, - sessions, - verificationTokens, + // users, + // accounts, + // sessions, + // verificationTokens, chats, - chatsRelations, - usersRelations, + // chatsRelations, + // messages, + // messagesRelations, + // usersRelations, }, }); export type DbClient = typeof db; + +export type Schema = { + chats: typeof chats; +};