feat: migrate to bun

This commit is contained in:
ARUNAVO RAY
2025-05-20 14:58:00 +05:30
parent 38206e7d3d
commit 94aff30dda
7 changed files with 57 additions and 55 deletions

View File

@@ -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. 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 GitHub account with a personal access token
- A Gitea instance with an access token - A Gitea instance with an access token
@@ -359,7 +359,7 @@ docker compose -f docker-compose.dev.yml up -d
## Technologies Used ## Technologies Used
- **Frontend**: Astro, React, Shadcn UI, Tailwind CSS v4 - **Frontend**: Astro, React, Shadcn UI, Tailwind CSS v4
- **Backend**: Node.js - **Backend**: Bun
- **Database**: SQLite (default) or PostgreSQL - **Database**: SQLite (default) or PostgreSQL
- **Caching/Queue**: Redis - **Caching/Queue**: Redis
- **API Integration**: GitHub API (Octokit), Gitea API - **API Integration**: GitHub API (Octokit), Gitea API

View File

@@ -3,31 +3,30 @@
"type": "module", "type": "module",
"version": "1.0.0", "version": "1.0.0",
"engines": { "engines": {
"node": ">=22.0.0" "bun": ">=1.2.9"
}, },
"scripts": { "scripts": {
"setup": "pnpm install && pnpm manage-db init", "setup": "pnpm install && pnpm manage-db init",
"dev": "astro dev", "dev": "bunx astro dev",
"dev:clean": "pnpm cleanup-db && pnpm manage-db init && astro dev", "dev:clean": "pnpm cleanup-db && pnpm manage-db init && bunx astro dev",
"build": "astro build", "build": "bunx astro build",
"cleanup-db": "rm -f gitea-mirror.db data/gitea-mirror.db", "cleanup-db": "rm -f gitea-mirror.db data/gitea-mirror.db",
"manage-db": "tsx scripts/manage-db.ts", "manage-db": "bun scripts/manage-db.ts",
"init-db": "tsx scripts/manage-db.ts init", "init-db": "bun scripts/manage-db.ts init",
"check-db": "tsx scripts/manage-db.ts check", "check-db": "bun scripts/manage-db.ts check",
"fix-db": "tsx scripts/manage-db.ts fix", "fix-db": "bun scripts/manage-db.ts fix",
"reset-users": "tsx scripts/manage-db.ts reset-users", "reset-users": "bun scripts/manage-db.ts reset-users",
"preview": "astro preview", "preview": "bunx astro preview",
"start": "node dist/server/entry.mjs", "start": "bun dist/server/entry.mjs",
"start:fresh": "pnpm cleanup-db && pnpm manage-db init && node dist/server/entry.mjs", "start:fresh": "pnpm cleanup-db && pnpm manage-db init && bun dist/server/entry.mjs",
"test": "vitest run", "test": "bunx vitest run",
"test:watch": "vitest", "test:watch": "bunx vitest",
"astro": "astro" "astro": "bunx astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "^4.2.6", "@astrojs/mdx": "^4.2.6",
"@astrojs/node": "^9.2.1", "@astrojs/node": "^9.2.1",
"@astrojs/react": "^4.2.7", "@astrojs/react": "^4.2.7",
"@libsql/client": "^0.15.4",
"@octokit/rest": "^21.1.1", "@octokit/rest": "^21.1.1",
"@radix-ui/react-avatar": "^1.1.4", "@radix-ui/react-avatar": "^1.1.4",
"@radix-ui/react-checkbox": "^1.1.5", "@radix-ui/react-checkbox": "^1.1.5",
@@ -54,7 +53,6 @@
"cmdk": "^1.1.1", "cmdk": "^1.1.1",
"drizzle-orm": "^0.41.0", "drizzle-orm": "^0.41.0",
"fuse.js": "^7.1.0", "fuse.js": "^7.1.0",
"ioredis": "^5.6.1",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"lucide-react": "^0.488.0", "lucide-react": "^0.488.0",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
@@ -73,12 +71,10 @@
"@testing-library/jest-dom": "^6.6.3", "@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0", "@testing-library/react": "^16.3.0",
"@types/bcryptjs": "^3.0.0", "@types/bcryptjs": "^3.0.0",
"@types/better-sqlite3": "^7.6.13",
"@types/jsonwebtoken": "^9.0.9", "@types/jsonwebtoken": "^9.0.9",
"@types/superagent": "^8.1.9", "@types/superagent": "^8.1.9",
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^4.4.0", "@vitejs/plugin-react": "^4.4.0",
"better-sqlite3": "^9.6.0",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"tsx": "^4.19.3", "tsx": "^4.19.3",
"vitest": "^3.1.1" "vitest": "^3.1.1"

View File

@@ -22,7 +22,7 @@ The application is built using:
- <span class="font-semibold text-foreground">React</span>: Component library for interactive UI elements - <span class="font-semibold text-foreground">React</span>: Component library for interactive UI elements
- <span class="font-semibold text-foreground">Shadcn UI</span>: UI component library built on Tailwind CSS - <span class="font-semibold text-foreground">Shadcn UI</span>: UI component library built on Tailwind CSS
- <span class="font-semibold text-foreground">SQLite</span>: Database for storing configuration and state - <span class="font-semibold text-foreground">SQLite</span>: Database for storing configuration and state
- <span class="font-semibold text-foreground">Node.js</span>: Runtime environment for the backend - <span class="font-semibold text-foreground">Bun</span>: Runtime environment for the backend
## Architecture Diagram ## Architecture Diagram
@@ -30,7 +30,7 @@ The application is built using:
graph TD graph TD
subgraph "Gitea Mirror" subgraph "Gitea Mirror"
Frontend["Frontend<br/>(Astro)"] Frontend["Frontend<br/>(Astro)"]
Backend["Backend<br/>(Node.js)"] Backend["Backend<br/>(Bun)"]
Database["Database<br/>(SQLite)"] Database["Database<br/>(SQLite)"]
Frontend <--> Backend Frontend <--> Backend
@@ -60,9 +60,9 @@ Key frontend components:
- **Configuration**: Settings for GitHub and Gitea connections - **Configuration**: Settings for GitHub and Gitea connections
- **Activity Log**: Detailed log of mirroring operations - **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 - Authentication and user management
- GitHub API integration - GitHub API integration

View File

@@ -23,7 +23,7 @@ The following environment variables can be used to configure Gitea Mirror:
| Variable | Description | Default Value | Example | | 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` | | `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` | | `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` | | `HOST` | Server host | `localhost` | `0.0.0.0` |

View File

@@ -16,7 +16,7 @@ Before you begin, make sure you have:
1. <span class="font-semibold text-foreground">A GitHub account with a personal access token</span> 1. <span class="font-semibold text-foreground">A GitHub account with a personal access token</span>
2. <span class="font-semibold text-foreground">A Gitea instance with an access token</span> 2. <span class="font-semibold text-foreground">A Gitea instance with an access token</span>
3. <span class="font-semibold text-foreground">Docker and docker-compose (recommended) or Node.js 18+ installed</span> 3. <span class="font-semibold text-foreground">Docker and docker-compose (recommended) or Bun 1.2.9+ installed</span>
## Installation Options ## Installation Options

View File

@@ -1,6 +1,6 @@
import { z } from "zod"; import { z } from "zod";
import { createClient } from "@libsql/client"; import { Database } from "bun:sqlite";
import { drizzle } from "drizzle-orm/libsql"; import { drizzle } from "drizzle-orm/bun-sqlite";
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core"; import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
import path from "path"; import path from "path";
@@ -11,11 +11,24 @@ const dataDir = path.join(process.cwd(), "data");
const dbUrl = const dbUrl =
process.env.DATABASE_URL || `file:${path.join(dataDir, "gitea-mirror.db")}`; process.env.DATABASE_URL || `file:${path.join(dataDir, "gitea-mirror.db")}`;
// Create a client connection to the database // Create a SQLite database instance using Bun's native driver
export const client = createClient({ url: dbUrl }); 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 // Create a drizzle instance
export const db = drizzle(client); export const db = drizzle(sqlite);
// Define the tables // Define the tables
export const users = sqliteTable("users", { export const users = sqliteTable("users", {

View File

@@ -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 // 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 // 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}`); console.log(`Connecting to Redis at: ${redisUrl}`);
// Configure Redis client with connection options // Configure Redis client with connection options
const redisOptions = { function createClient() {
retryStrategy: (times: number) => { return new RedisClient(redisUrl, {
// Retry with exponential backoff up to 30 seconds autoReconnect: true,
const delay = Math.min(times * 100, 3000); });
console.log(`Redis connection attempt ${times} failed. Retrying in ${delay}ms...`); }
return delay;
}, export const redis = createClient();
maxRetriesPerRequest: 5, export const redisPublisher = createClient();
enableReadyCheck: true, export const redisSubscriber = createClient();
connectTimeout: 10000,
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...'));