feat: add multiple package sync sources and API integration

- Added undici dependency and implemented three package fetcher variants (simple text parsing, v2 with better error handling, and official repository sync)
- Integrated real API calls in PlatformSelector and PackageBrowser components with fallback to mock data
- Extended sync API route to support multiple data sources (debian-simple, ubuntu-simple, debian-official-v2, etc.) with platform initialization
This commit is contained in:
Yusuf İpek
2025-11-10 19:12:46 +03:00
parent 596bba0832
commit 08f35aedbc
25 changed files with 2152 additions and 102 deletions
+90
View File
@@ -0,0 +1,90 @@
import { Platform, Package, FilterOptions } from '@/types'
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3002/api'
class ApiClient {
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const url = `${API_BASE_URL}${endpoint}`
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
...options.headers,
},
...options,
})
if (!response.ok) {
throw new Error(`API request failed: ${response.statusText}`)
}
return response.json()
}
// Platform operations
async getPlatforms(): Promise<Platform[]> {
return this.request<Platform[]>('/platforms')
}
async getPlatform(id: string): Promise<Platform | null> {
try {
return await this.request<Platform>(`/platforms/${id}`)
} catch (error) {
return null
}
}
// Package operations
async getPackages(filters: FilterOptions = {}): Promise<{ packages: Package[], total: number }> {
const params = new URLSearchParams()
if (filters.platform_id) params.append('platform_id', filters.platform_id)
if (filters.category_id) params.append('category_id', filters.category_id.toString())
if (filters.type) params.append('type', filters.type)
if (filters.repository) params.append('repository', filters.repository)
if (filters.search) params.append('search', filters.search)
if (filters.limit) params.append('limit', filters.limit.toString())
if (filters.offset) params.append('offset', filters.offset.toString())
if (filters.sort_by) params.append('sort_by', filters.sort_by)
if (filters.sort_order) params.append('sort_order', filters.sort_order)
const query = params.toString() ? `?${params.toString()}` : ''
return this.request<{ packages: Package[], total: number }>(`/packages${query}`)
}
async getPackage(id: string): Promise<Package | null> {
try {
return await this.request<Package>(`/packages/${id}`)
} catch (error) {
return null
}
}
// Sync operations
async syncDebianPackages(): Promise<{ message: string, timestamp: string }> {
return this.request<{ message: string, timestamp: string }>('/sync', {
method: 'POST',
body: JSON.stringify({ source: 'debian-official' }),
})
}
async syncUbuntuPackages(): Promise<{ message: string, timestamp: string }> {
return this.request<{ message: string, timestamp: string }>('/sync', {
method: 'POST',
body: JSON.stringify({ source: 'ubuntu-official' }),
})
}
async syncAllDebianPackages(): Promise<{ message: string, timestamp: string }> {
return this.request<{ message: string, timestamp: string }>('/sync', {
method: 'POST',
body: JSON.stringify({ source: 'all-official' }),
})
}
async getSyncStatus(): Promise<{ status: string, last_sync: string | null, platforms: string[] }> {
return this.request<{ status: string, last_sync: string | null, platforms: string[] }>('/sync')
}
}
export const apiClient = new ApiClient()
+5 -4
View File
@@ -13,8 +13,9 @@ export function generateScript(packages: SelectedPackage[], platform: Platform):
function createScriptContent(packages: SelectedPackage[], platform: Platform): string {
switch (platform.id) {
case 'debian':
case 'ubuntu':
return generateUbuntuScript(packages)
return generateDebianBasedScript(packages, platform.name)
case 'fedora':
return generateFedoraScript(packages)
case 'arch':
@@ -28,18 +29,18 @@ function createScriptContent(packages: SelectedPackage[], platform: Platform): s
}
}
function generateUbuntuScript(packages: SelectedPackage[]): string {
function generateDebianBasedScript(packages: SelectedPackage[], platformName: string): string {
const packageNames = packages.map(p => p.name).join(' ')
return `#!/bin/bash
# RepoHub Installation Script for Ubuntu/Debian
# RepoHub Installation Script for ${platformName}
# Generated on ${new Date().toISOString()}
# This script is idempotent and safe to run multiple times
set -e
echo "Starting package installation for Ubuntu/Debian..."
echo "Starting package installation for ${platformName}..."
# Update package lists
echo "Updating package lists..."