feat: prepare for Vercel deployment with PostgreSQL migration

This commit is contained in:
kaunghtut24 2025-06-16 15:36:08 +05:30
parent 38ab8a260c
commit ffdc8c5b6c
8 changed files with 97 additions and 27 deletions

View file

@ -1,11 +1,14 @@
import { defineConfig } from 'drizzle-kit'; import { defineConfig } from 'drizzle-kit';
import path from 'path'; import * as dotenv from 'dotenv';
dotenv.config();
export default defineConfig({ export default defineConfig({
dialect: 'sqlite',
schema: './src/lib/db/schema.ts', schema: './src/lib/db/schema.ts',
out: './drizzle', out: './drizzle',
driver: 'pg',
dbCredentials: { dbCredentials: {
url: path.join(process.cwd(), 'data', 'db.sqlite'), connectionString: process.env.POSTGRES_URL!,
}, },
verbose: true,
strict: true,
}); });

View file

@ -8,7 +8,15 @@ const nextConfig = {
}, },
], ],
}, },
serverExternalPackages: ['pdf-parse'], // Enable experimental features for better performance
experimental: {
serverActions: true,
serverComponentsExternalPackages: ['@vercel/postgres'],
},
// Configure environment variables
env: {
POSTGRES_URL: process.env.POSTGRES_URL,
},
}; };
export default nextConfig; export default nextConfig;

View file

@ -9,7 +9,11 @@
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint",
"format:write": "prettier . --write", "format:write": "prettier . --write",
"db:push": "drizzle-kit push" "db:push": "drizzle-kit push:pg",
"db:generate": "drizzle-kit generate:pg",
"db:migrate": "tsx src/lib/db/migrate.ts",
"db:studio": "drizzle-kit studio",
"postdeploy": "node vercel-post-deploy.js"
}, },
"dependencies": { "dependencies": {
"@headlessui/react": "^2.2.0", "@headlessui/react": "^2.2.0",
@ -46,7 +50,9 @@
"tailwind-merge": "^2.2.2", "tailwind-merge": "^2.2.2",
"winston": "^3.17.0", "winston": "^3.17.0",
"yet-another-react-lightbox": "^3.17.2", "yet-another-react-lightbox": "^3.17.2",
"zod": "^3.22.4" "zod": "^3.22.4",
"pg": "^8.11.3",
"@vercel/postgres": "^0.7.2"
}, },
"devDependencies": { "devDependencies": {
"@types/better-sqlite3": "^7.6.12", "@types/better-sqlite3": "^7.6.12",
@ -63,6 +69,7 @@
"postcss": "^8", "postcss": "^8",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"tailwindcss": "^3.3.0", "tailwindcss": "^3.3.0",
"typescript": "^5" "typescript": "^5",
"@types/pg": "^8.11.2"
} }
} }

View file

@ -1,11 +1,9 @@
import { drizzle } from 'drizzle-orm/better-sqlite3'; import { drizzle } from 'drizzle-orm/vercel-postgres';
import Database from 'better-sqlite3'; import { sql } from '@vercel/postgres';
import * as schema from './schema'; import * as schema from './schema';
import path from 'path';
const DATA_DIR = process.env.DATA_DIR || process.cwd(); // Create a PostgreSQL client using Vercel Postgres
const sqlite = new Database(path.join(DATA_DIR, './data/db.sqlite')); const db = drizzle(sql, {
const db = drizzle(sqlite, {
schema: schema, schema: schema,
}); });

View file

@ -1,5 +1,22 @@
import db from './'; import { drizzle } from 'drizzle-orm/vercel-postgres';
import { migrate } from 'drizzle-orm/better-sqlite3/migrator'; import { migrate } from 'drizzle-orm/vercel-postgres/migrator';
import { sql } from '@vercel/postgres';
import path from 'path'; import path from 'path';
migrate(db, { migrationsFolder: path.join(process.cwd(), 'drizzle') }); async function main() {
const db = drizzle(sql);
console.log('Running migrations...');
await migrate(db, { migrationsFolder: path.join(process.cwd(), 'drizzle') });
console.log('Migrations completed!');
process.exit(0);
}
main().catch((err) => {
console.error('Migration failed!');
console.error(err);
process.exit(1);
});

View file

@ -1,15 +1,14 @@
import { sql } from 'drizzle-orm'; import { sql } from 'drizzle-orm';
import { text, integer, sqliteTable } from 'drizzle-orm/sqlite-core'; import { text, integer, pgTable, timestamp, jsonb } from 'drizzle-orm/pg-core';
export const messages = sqliteTable('messages', { export const messages = pgTable('messages', {
id: integer('id').primaryKey(), id: integer('id').primaryKey().notNull(),
content: text('content').notNull(), content: text('content').notNull(),
chatId: text('chatId').notNull(), chatId: text('chatId').notNull(),
messageId: text('messageId').notNull(), messageId: text('messageId').notNull(),
role: text('type', { enum: ['assistant', 'user'] }), role: text('type', { enum: ['assistant', 'user'] }),
metadata: text('metadata', { metadata: jsonb('metadata'),
mode: 'json', createdAt: timestamp('created_at').defaultNow(),
}),
}); });
interface File { interface File {
@ -17,12 +16,10 @@ interface File {
fileId: string; fileId: string;
} }
export const chats = sqliteTable('chats', { export const chats = pgTable('chats', {
id: text('id').primaryKey(), id: text('id').primaryKey(),
title: text('title').notNull(), title: text('title').notNull(),
createdAt: text('createdAt').notNull(), createdAt: timestamp('created_at').defaultNow(),
focusMode: text('focusMode').notNull(), focusMode: text('focusMode').notNull(),
files: text('files', { mode: 'json' }) files: jsonb('files').$type<File[]>().default(sql`'[]'::jsonb`),
.$type<File[]>()
.default(sql`'[]'`),
}); });

14
vercel-post-deploy.js Normal file
View file

@ -0,0 +1,14 @@
const { execSync } = require('child_process');
async function runMigrations() {
try {
console.log('Running database migrations...');
execSync('npm run db:migrate', { stdio: 'inherit' });
console.log('Migrations completed successfully!');
} catch (error) {
console.error('Migration failed:', error);
process.exit(1);
}
}
runMigrations();

26
vercel.json Normal file
View file

@ -0,0 +1,26 @@
{
"version": 2,
"buildCommand": "npm run build",
"installCommand": "npm install",
"framework": "nextjs",
"builds": [
{
"src": "package.json",
"use": "@vercel/next"
}
],
"env": {
"POSTGRES_URL": "@postgres_url",
"OPENAI_API_KEY": "@openai_api_key",
"GROQ_API_KEY": "@groq_api_key",
"ANTHROPIC_API_KEY": "@anthropic_api_key",
"GEMINI_API_KEY": "@gemini_api_key",
"DEEPSEEK_API_KEY": "@deepseek_api_key",
"SEARXNG_API_URL": "@searxng_api_url",
"OLLAMA_API_URL": "@ollama_api_url",
"LM_STUDIO_API_URL": "@lm_studio_api_url",
"CUSTOM_OPENAI_API_URL": "@custom_openai_api_url",
"CUSTOM_OPENAI_API_KEY": "@custom_openai_api_key",
"CUSTOM_OPENAI_MODEL_NAME": "@custom_openai_model_name"
}
}