diff --git a/src/components/config/AutomationSettings.tsx b/src/components/config/AutomationSettings.tsx index 2692da0..d51f888 100644 --- a/src/components/config/AutomationSettings.tsx +++ b/src/components/config/AutomationSettings.tsx @@ -195,21 +195,27 @@ export function AutomationSettings({ Last sync - + {scheduleConfig.lastRun ? formatDate(scheduleConfig.lastRun) : "Never"} - {scheduleConfig.enabled && scheduleConfig.nextRun && ( -
- - - Next sync - - - {formatDate(scheduleConfig.nextRun)} - + {scheduleConfig.enabled ? ( + scheduleConfig.nextRun && ( +
+ + + Next sync + + + {formatDate(scheduleConfig.nextRun)} + +
+ ) + ) : ( +
+ Enable automatic syncing to schedule periodic repository updates
)}
@@ -307,23 +313,27 @@ export function AutomationSettings({ Last cleanup
- + {cleanupConfig.lastRun ? formatDate(cleanupConfig.lastRun) : "Never"} - {cleanupConfig.enabled && cleanupConfig.nextRun && ( -
- - - Next cleanup - - - {cleanupConfig.nextRun - ? formatDate(cleanupConfig.nextRun) - : "Calculating..."} - + {cleanupConfig.enabled ? ( + cleanupConfig.nextRun && ( +
+ + + Next cleanup + + + {formatDate(cleanupConfig.nextRun)} + +
+ ) + ) : ( +
+ Enable automatic cleanup to optimize database storage
)}
diff --git a/src/components/config/ConfigTabs.tsx b/src/components/config/ConfigTabs.tsx index 535b071..b332137 100644 --- a/src/components/config/ConfigTabs.tsx +++ b/src/components/config/ConfigTabs.tsx @@ -51,11 +51,11 @@ export function ConfigTabs() { }, scheduleConfig: { enabled: false, - interval: 3600, + interval: 86400, // Default to daily (24 hours) instead of hourly }, cleanupConfig: { enabled: false, - retentionDays: 604800, // 7 days in seconds + retentionDays: 604800, // 7 days in seconds - Default retention period }, mirrorOptions: { mirrorReleases: false, diff --git a/src/lib/utils/config-defaults.ts b/src/lib/utils/config-defaults.ts new file mode 100644 index 0000000..a1f4365 --- /dev/null +++ b/src/lib/utils/config-defaults.ts @@ -0,0 +1,126 @@ +import { db, configs } from "@/lib/db"; +import { eq } from "drizzle-orm"; +import { v4 as uuidv4 } from "uuid"; +import { encrypt } from "@/lib/utils/encryption"; + +export interface DefaultConfigOptions { + userId: string; + envOverrides?: { + githubToken?: string; + githubUsername?: string; + giteaUrl?: string; + giteaToken?: string; + giteaUsername?: string; + scheduleEnabled?: boolean; + scheduleInterval?: number; + cleanupEnabled?: boolean; + cleanupRetentionDays?: number; + }; +} + +/** + * Creates a default configuration for a new user with sensible defaults + * Environment variables can override these defaults + */ +export async function createDefaultConfig({ userId, envOverrides = {} }: DefaultConfigOptions) { + // Check if config already exists + const existingConfig = await db + .select() + .from(configs) + .where(eq(configs.userId, userId)) + .limit(1); + + if (existingConfig.length > 0) { + return existingConfig[0]; + } + + // Read environment variables for overrides + const githubToken = envOverrides.githubToken || process.env.GITHUB_TOKEN || ""; + const githubUsername = envOverrides.githubUsername || process.env.GITHUB_USERNAME || ""; + const giteaUrl = envOverrides.giteaUrl || process.env.GITEA_URL || ""; + const giteaToken = envOverrides.giteaToken || process.env.GITEA_TOKEN || ""; + const giteaUsername = envOverrides.giteaUsername || process.env.GITEA_USERNAME || ""; + + // Schedule config from env + const scheduleEnabled = envOverrides.scheduleEnabled ?? + (process.env.SCHEDULE_ENABLED === "true" ? true : false); + const scheduleInterval = envOverrides.scheduleInterval ?? + (process.env.SCHEDULE_INTERVAL ? parseInt(process.env.SCHEDULE_INTERVAL, 10) : 86400); // Default: daily + + // Cleanup config from env + const cleanupEnabled = envOverrides.cleanupEnabled ?? + (process.env.CLEANUP_ENABLED === "true" ? true : false); + const cleanupRetentionDays = envOverrides.cleanupRetentionDays ?? + (process.env.CLEANUP_RETENTION_DAYS ? parseInt(process.env.CLEANUP_RETENTION_DAYS, 10) * 86400 : 604800); // Default: 7 days + + // Create default configuration + const configId = uuidv4(); + const defaultConfig = { + id: configId, + userId, + name: "Default Configuration", + isActive: true, + githubConfig: { + owner: githubUsername, + type: "personal", + token: githubToken ? encrypt(githubToken) : "", + includeStarred: false, + includeForks: true, + includeArchived: false, + includePrivate: false, + includePublic: true, + includeOrganizations: [], + starredReposOrg: "starred", + mirrorStrategy: "preserve", + defaultOrg: "github-mirrors", + }, + giteaConfig: { + url: giteaUrl, + token: giteaToken ? encrypt(giteaToken) : "", + defaultOwner: giteaUsername, + mirrorInterval: "8h", + lfs: false, + wiki: false, + visibility: "public", + createOrg: true, + addTopics: true, + preserveVisibility: false, + forkStrategy: "reference", + }, + include: [], + exclude: [], + scheduleConfig: { + enabled: scheduleEnabled, + interval: scheduleInterval, + concurrent: false, + batchSize: 10, + lastRun: null, + nextRun: scheduleEnabled ? new Date(Date.now() + scheduleInterval * 1000) : null, + }, + cleanupConfig: { + enabled: cleanupEnabled, + retentionDays: cleanupRetentionDays, + lastRun: null, + nextRun: cleanupEnabled ? new Date(Date.now() + getCleanupInterval(cleanupRetentionDays) * 1000) : null, + }, + createdAt: new Date(), + updatedAt: new Date(), + }; + + // Insert the default config + await db.insert(configs).values(defaultConfig); + + return defaultConfig; +} + +/** + * Calculate cleanup interval based on retention period + */ +function getCleanupInterval(retentionSeconds: number): number { + const days = retentionSeconds / 86400; + if (days <= 1) return 21600; // 6 hours + if (days <= 3) return 43200; // 12 hours + if (days <= 7) return 86400; // 24 hours + if (days <= 30) return 172800; // 48 hours + return 604800; // 1 week +} \ No newline at end of file diff --git a/src/pages/api/config/index.ts b/src/pages/api/config/index.ts index 2b1105d..31a1801 100644 --- a/src/pages/api/config/index.ts +++ b/src/pages/api/config/index.ts @@ -13,6 +13,7 @@ import { mapDbCleanupToUi } from "@/lib/utils/config-mapper"; import { encrypt, decrypt, migrateToken } from "@/lib/utils/encryption"; +import { createDefaultConfig } from "@/lib/utils/config-defaults"; export const POST: APIRoute = async ({ request }) => { try { @@ -188,58 +189,20 @@ export const GET: APIRoute = async ({ request }) => { .limit(1); if (config.length === 0) { - // Return a default empty configuration with database structure - const defaultDbConfig = { - githubConfig: { - owner: "", - type: "personal", - token: "", - includeStarred: false, - includeForks: true, - includeArchived: false, - includePrivate: false, - includePublic: true, - includeOrganizations: [], - starredReposOrg: "starred", - mirrorStrategy: "preserve", - defaultOrg: "github-mirrors", - }, - giteaConfig: { - url: "", - token: "", - defaultOwner: "", - mirrorInterval: "8h", - lfs: false, - wiki: false, - visibility: "public", - createOrg: true, - addTopics: true, - preserveVisibility: false, - forkStrategy: "reference", - }, - }; + // Create default configuration for the user + const defaultConfig = await createDefaultConfig({ userId }); - const uiConfig = mapDbToUiConfig(defaultDbConfig); + // Map the created config to UI format + const uiConfig = mapDbToUiConfig(defaultConfig); + const uiScheduleConfig = mapDbScheduleToUi(defaultConfig.scheduleConfig); + const uiCleanupConfig = mapDbCleanupToUi(defaultConfig.cleanupConfig); return new Response( JSON.stringify({ - id: null, - userId: userId, - name: "Default Configuration", - isActive: true, + ...defaultConfig, ...uiConfig, - scheduleConfig: { - enabled: false, - interval: 3600, - lastRun: null, - nextRun: null, - }, - cleanupConfig: { - enabled: false, - retentionDays: 604800, // 7 days in seconds - lastRun: null, - nextRun: null, - }, + scheduleConfig: uiScheduleConfig, + cleanupConfig: uiCleanupConfig, }), { status: 200,