From 94aff30ddac4f789e243370ff09ae2217be3168a Mon Sep 17 00:00:00 2001 From: ARUNAVO RAY Date: Tue, 20 May 2025 14:58:00 +0530 Subject: [PATCH] feat: migrate to bun --- README.md | 6 ++--- package.json | 34 +++++++++++++--------------- src/content/docs/architecture.md | 8 +++---- src/content/docs/configuration.md | 2 +- src/content/docs/quickstart.md | 2 +- src/lib/db/index.ts | 23 ++++++++++++++----- src/lib/redis.ts | 37 +++++++++++++------------------ 7 files changed, 57 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index dabdc28..1132603 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,9 @@ Easily configure your GitHub and Gitea connections, set up automatic mirroring s See the [Quick Start Guide](docs/quickstart.md) for detailed instructions on getting up and running quickly. -### Prerequisites +-### Prerequisites -- Node.js 22 or later +- Bun 1.2.9 or later - A GitHub account with a personal access token - A Gitea instance with an access token @@ -359,7 +359,7 @@ docker compose -f docker-compose.dev.yml up -d ## Technologies Used - **Frontend**: Astro, React, Shadcn UI, Tailwind CSS v4 -- **Backend**: Node.js + - **Backend**: Bun - **Database**: SQLite (default) or PostgreSQL - **Caching/Queue**: Redis - **API Integration**: GitHub API (Octokit), Gitea API diff --git a/package.json b/package.json index 9e206c4..aae84cf 100644 --- a/package.json +++ b/package.json @@ -3,31 +3,30 @@ "type": "module", "version": "1.0.0", "engines": { - "node": ">=22.0.0" + "bun": ">=1.2.9" }, "scripts": { "setup": "pnpm install && pnpm manage-db init", - "dev": "astro dev", - "dev:clean": "pnpm cleanup-db && pnpm manage-db init && astro dev", - "build": "astro build", + "dev": "bunx astro dev", + "dev:clean": "pnpm cleanup-db && pnpm manage-db init && bunx astro dev", + "build": "bunx astro build", "cleanup-db": "rm -f gitea-mirror.db data/gitea-mirror.db", - "manage-db": "tsx scripts/manage-db.ts", - "init-db": "tsx scripts/manage-db.ts init", - "check-db": "tsx scripts/manage-db.ts check", - "fix-db": "tsx scripts/manage-db.ts fix", - "reset-users": "tsx scripts/manage-db.ts reset-users", - "preview": "astro preview", - "start": "node dist/server/entry.mjs", - "start:fresh": "pnpm cleanup-db && pnpm manage-db init && node dist/server/entry.mjs", - "test": "vitest run", - "test:watch": "vitest", - "astro": "astro" + "manage-db": "bun scripts/manage-db.ts", + "init-db": "bun scripts/manage-db.ts init", + "check-db": "bun scripts/manage-db.ts check", + "fix-db": "bun scripts/manage-db.ts fix", + "reset-users": "bun scripts/manage-db.ts reset-users", + "preview": "bunx astro preview", + "start": "bun dist/server/entry.mjs", + "start:fresh": "pnpm cleanup-db && pnpm manage-db init && bun dist/server/entry.mjs", + "test": "bunx vitest run", + "test:watch": "bunx vitest", + "astro": "bunx astro" }, "dependencies": { "@astrojs/mdx": "^4.2.6", "@astrojs/node": "^9.2.1", "@astrojs/react": "^4.2.7", - "@libsql/client": "^0.15.4", "@octokit/rest": "^21.1.1", "@radix-ui/react-avatar": "^1.1.4", "@radix-ui/react-checkbox": "^1.1.5", @@ -54,7 +53,6 @@ "cmdk": "^1.1.1", "drizzle-orm": "^0.41.0", "fuse.js": "^7.1.0", - "ioredis": "^5.6.1", "jsonwebtoken": "^9.0.2", "lucide-react": "^0.488.0", "next-themes": "^0.4.6", @@ -73,12 +71,10 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@types/bcryptjs": "^3.0.0", - "@types/better-sqlite3": "^7.6.13", "@types/jsonwebtoken": "^9.0.9", "@types/superagent": "^8.1.9", "@types/uuid": "^10.0.0", "@vitejs/plugin-react": "^4.4.0", - "better-sqlite3": "^9.6.0", "jsdom": "^26.1.0", "tsx": "^4.19.3", "vitest": "^3.1.1" diff --git a/src/content/docs/architecture.md b/src/content/docs/architecture.md index 7b8b7a9..4045f4b 100644 --- a/src/content/docs/architecture.md +++ b/src/content/docs/architecture.md @@ -22,7 +22,7 @@ The application is built using: - React: Component library for interactive UI elements - Shadcn UI: UI component library built on Tailwind CSS - SQLite: Database for storing configuration and state -- Node.js: Runtime environment for the backend +- Bun: Runtime environment for the backend ## Architecture Diagram @@ -30,7 +30,7 @@ The application is built using: graph TD subgraph "Gitea Mirror" Frontend["Frontend
(Astro)"] - Backend["Backend
(Node.js)"] + Backend["Backend
(Bun)"] Database["Database
(SQLite)"] Frontend <--> Backend @@ -60,9 +60,9 @@ Key frontend components: - **Configuration**: Settings for GitHub and Gitea connections - **Activity Log**: Detailed log of mirroring operations -### Backend (Node.js) +### Backend (Bun) -The backend is built with Node.js and provides API endpoints for the frontend to interact with. It handles: +The backend is built with Bun and provides API endpoints for the frontend to interact with. It handles: - Authentication and user management - GitHub API integration diff --git a/src/content/docs/configuration.md b/src/content/docs/configuration.md index 381ff41..ce4c713 100644 --- a/src/content/docs/configuration.md +++ b/src/content/docs/configuration.md @@ -23,7 +23,7 @@ The following environment variables can be used to configure Gitea Mirror: | Variable | Description | Default Value | Example | |----------|-------------|---------------|---------| -| `NODE_ENV` | Node environment (development, production, test) | `development` | `production` | +| `NODE_ENV` | Runtime environment (development, production, test) | `development` | `production` | | `DATABASE_URL` | SQLite database URL | `sqlite://data/gitea-mirror.db` | `sqlite://path/to/your/database.db` | | `JWT_SECRET` | Secret key for JWT authentication | `your-secret-key-change-this-in-production` | `your-secure-random-string` | | `HOST` | Server host | `localhost` | `0.0.0.0` | diff --git a/src/content/docs/quickstart.md b/src/content/docs/quickstart.md index 8efa109..4ae544d 100644 --- a/src/content/docs/quickstart.md +++ b/src/content/docs/quickstart.md @@ -16,7 +16,7 @@ Before you begin, make sure you have: 1. A GitHub account with a personal access token 2. A Gitea instance with an access token -3. Docker and docker-compose (recommended) or Node.js 18+ installed +3. Docker and docker-compose (recommended) or Bun 1.2.9+ installed ## Installation Options diff --git a/src/lib/db/index.ts b/src/lib/db/index.ts index 0ae592a..bb9307f 100644 --- a/src/lib/db/index.ts +++ b/src/lib/db/index.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -import { createClient } from "@libsql/client"; -import { drizzle } from "drizzle-orm/libsql"; +import { Database } from "bun:sqlite"; +import { drizzle } from "drizzle-orm/bun-sqlite"; import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core"; import path from "path"; @@ -11,11 +11,24 @@ const dataDir = path.join(process.cwd(), "data"); const dbUrl = process.env.DATABASE_URL || `file:${path.join(dataDir, "gitea-mirror.db")}`; -// Create a client connection to the database -export const client = createClient({ url: dbUrl }); +// Create a SQLite database instance using Bun's native driver +export const sqlite = new Database(dbUrl); + +// Simple async wrapper around Bun's SQLite API for compatibility +export const client = { + async execute(sql: string, params?: any[]) { + const stmt = sqlite.query(sql); + if (/^\s*select/i.test(sql)) { + const rows = stmt.all(params ?? []); + return { rows } as { rows: any[] }; + } + stmt.run(params ?? []); + return { rows: [] } as { rows: any[] }; + }, +}; // Create a drizzle instance -export const db = drizzle(client); +export const db = drizzle(sqlite); // Define the tables export const users = sqliteTable("users", { diff --git a/src/lib/redis.ts b/src/lib/redis.ts index 6c59d9d..a5686e7 100644 --- a/src/lib/redis.ts +++ b/src/lib/redis.ts @@ -1,30 +1,23 @@ -import Redis from "ioredis"; +import { RedisClient } from "bun"; // Connect to Redis using REDIS_URL environment variable or default to redis://redis:6379 // This ensures we have a fallback URL when running with Docker Compose -const redisUrl = process.env.REDIS_URL ?? 'redis://redis:6379'; +const redisUrl = process.env.REDIS_URL ?? "redis://redis:6379"; console.log(`Connecting to Redis at: ${redisUrl}`); // Configure Redis client with connection options -const redisOptions = { - retryStrategy: (times: number) => { - // Retry with exponential backoff up to 30 seconds - const delay = Math.min(times * 100, 3000); - console.log(`Redis connection attempt ${times} failed. Retrying in ${delay}ms...`); - return delay; - }, - maxRetriesPerRequest: 5, - enableReadyCheck: true, - connectTimeout: 10000, +function createClient() { + return new RedisClient(redisUrl, { + autoReconnect: true, + }); +} + +export const redis = createClient(); +export const redisPublisher = createClient(); +export const redisSubscriber = createClient(); + +redis.onconnect = () => console.log("Connected to Redis server"); +redis.onclose = (err) => { + if (err) console.error("Disconnected from Redis server:", err); }; - -export const redis = new Redis(redisUrl, redisOptions); -export const redisPublisher = new Redis(redisUrl, redisOptions); // For publishing -export const redisSubscriber = new Redis(redisUrl, redisOptions); // For subscribing - -// Log connection events -redis.on('connect', () => console.log('Redis client connected')); -redis.on('error', (err) => console.error('Redis client error:', err)); -redis.on('ready', () => console.log('Redis client ready')); -redis.on('reconnecting', () => console.log('Redis client reconnecting...'));