mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2025-12-08 12:36:44 +03:00
feat: enhance API config handling by adding mapping functions for UI and database structures
This commit is contained in:
134
src/lib/utils/config-mapper.ts
Normal file
134
src/lib/utils/config-mapper.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Maps between UI config structure and database schema structure
|
||||
*/
|
||||
|
||||
import type {
|
||||
GitHubConfig,
|
||||
GiteaConfig,
|
||||
MirrorOptions,
|
||||
AdvancedOptions,
|
||||
SaveConfigApiRequest
|
||||
} from "@/types/config";
|
||||
|
||||
interface DbGitHubConfig {
|
||||
username: string;
|
||||
token?: string;
|
||||
skipForks: boolean;
|
||||
privateRepositories: boolean;
|
||||
mirrorIssues: boolean;
|
||||
mirrorWiki: boolean;
|
||||
mirrorStarred: boolean;
|
||||
useSpecificUser: boolean;
|
||||
singleRepo?: string;
|
||||
includeOrgs: string[];
|
||||
excludeOrgs: string[];
|
||||
mirrorPublicOrgs: boolean;
|
||||
publicOrgs: string[];
|
||||
skipStarredIssues: boolean;
|
||||
}
|
||||
|
||||
interface DbGiteaConfig {
|
||||
username: string;
|
||||
url: string;
|
||||
token: string;
|
||||
organization?: string;
|
||||
visibility: "public" | "private" | "limited";
|
||||
starredReposOrg: string;
|
||||
preserveOrgStructure: boolean;
|
||||
mirrorStrategy?: "preserve" | "single-org" | "flat-user";
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps UI config structure to database schema structure
|
||||
*/
|
||||
export function mapUiToDbConfig(
|
||||
githubConfig: GitHubConfig,
|
||||
giteaConfig: GiteaConfig,
|
||||
mirrorOptions: MirrorOptions,
|
||||
advancedOptions: AdvancedOptions
|
||||
): { githubConfig: DbGitHubConfig; giteaConfig: DbGiteaConfig } {
|
||||
// Map GitHub config with fields from mirrorOptions and advancedOptions
|
||||
const dbGithubConfig: DbGitHubConfig = {
|
||||
username: githubConfig.username,
|
||||
token: githubConfig.token,
|
||||
privateRepositories: githubConfig.privateRepositories,
|
||||
mirrorStarred: githubConfig.mirrorStarred,
|
||||
|
||||
// From mirrorOptions
|
||||
mirrorIssues: mirrorOptions.mirrorMetadata && mirrorOptions.metadataComponents.issues,
|
||||
mirrorWiki: mirrorOptions.mirrorMetadata && mirrorOptions.metadataComponents.wiki,
|
||||
|
||||
// From advancedOptions
|
||||
skipForks: advancedOptions.skipForks,
|
||||
skipStarredIssues: advancedOptions.skipStarredIssues,
|
||||
|
||||
// Default values for fields not in UI
|
||||
useSpecificUser: false,
|
||||
includeOrgs: [],
|
||||
excludeOrgs: [],
|
||||
mirrorPublicOrgs: false,
|
||||
publicOrgs: [],
|
||||
};
|
||||
|
||||
// Gitea config remains mostly the same
|
||||
const dbGiteaConfig: DbGiteaConfig = {
|
||||
...giteaConfig,
|
||||
};
|
||||
|
||||
return {
|
||||
githubConfig: dbGithubConfig,
|
||||
giteaConfig: dbGiteaConfig,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps database schema structure to UI config structure
|
||||
*/
|
||||
export function mapDbToUiConfig(dbConfig: any): {
|
||||
githubConfig: GitHubConfig;
|
||||
giteaConfig: GiteaConfig;
|
||||
mirrorOptions: MirrorOptions;
|
||||
advancedOptions: AdvancedOptions;
|
||||
} {
|
||||
const githubConfig: GitHubConfig = {
|
||||
username: dbConfig.githubConfig?.username || "",
|
||||
token: dbConfig.githubConfig?.token || "",
|
||||
privateRepositories: dbConfig.githubConfig?.privateRepositories || false,
|
||||
mirrorStarred: dbConfig.githubConfig?.mirrorStarred || false,
|
||||
};
|
||||
|
||||
const giteaConfig: GiteaConfig = {
|
||||
url: dbConfig.giteaConfig?.url || "",
|
||||
username: dbConfig.giteaConfig?.username || "",
|
||||
token: dbConfig.giteaConfig?.token || "",
|
||||
organization: dbConfig.giteaConfig?.organization || "github-mirrors",
|
||||
visibility: dbConfig.giteaConfig?.visibility || "public",
|
||||
starredReposOrg: dbConfig.giteaConfig?.starredReposOrg || "github",
|
||||
preserveOrgStructure: dbConfig.giteaConfig?.preserveOrgStructure || false,
|
||||
mirrorStrategy: dbConfig.giteaConfig?.mirrorStrategy,
|
||||
};
|
||||
|
||||
const mirrorOptions: MirrorOptions = {
|
||||
mirrorReleases: false, // Not stored in DB yet
|
||||
mirrorMetadata: dbConfig.githubConfig?.mirrorIssues || dbConfig.githubConfig?.mirrorWiki || false,
|
||||
metadataComponents: {
|
||||
issues: dbConfig.githubConfig?.mirrorIssues || false,
|
||||
pullRequests: false, // Not stored in DB yet
|
||||
labels: false, // Not stored in DB yet
|
||||
milestones: false, // Not stored in DB yet
|
||||
wiki: dbConfig.githubConfig?.mirrorWiki || false,
|
||||
},
|
||||
};
|
||||
|
||||
const advancedOptions: AdvancedOptions = {
|
||||
skipForks: dbConfig.githubConfig?.skipForks || false,
|
||||
skipStarredIssues: dbConfig.githubConfig?.skipStarredIssues || false,
|
||||
};
|
||||
|
||||
return {
|
||||
githubConfig,
|
||||
giteaConfig,
|
||||
mirrorOptions,
|
||||
advancedOptions,
|
||||
};
|
||||
}
|
||||
@@ -4,18 +4,19 @@ import { v4 as uuidv4 } from "uuid";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { calculateCleanupInterval } from "@/lib/cleanup-service";
|
||||
import { createSecureErrorResponse } from "@/lib/utils";
|
||||
import { mapUiToDbConfig, mapDbToUiConfig } from "@/lib/utils/config-mapper";
|
||||
|
||||
export const POST: APIRoute = async ({ request }) => {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const { userId, githubConfig, giteaConfig, scheduleConfig, cleanupConfig } = body;
|
||||
const { userId, githubConfig, giteaConfig, scheduleConfig, cleanupConfig, mirrorOptions, advancedOptions } = body;
|
||||
|
||||
if (!userId || !githubConfig || !giteaConfig || !scheduleConfig || !cleanupConfig) {
|
||||
if (!userId || !githubConfig || !giteaConfig || !scheduleConfig || !cleanupConfig || !mirrorOptions || !advancedOptions) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
message:
|
||||
"userId, githubConfig, giteaConfig, scheduleConfig, and cleanupConfig are required.",
|
||||
"userId, githubConfig, giteaConfig, scheduleConfig, cleanupConfig, mirrorOptions, and advancedOptions are required.",
|
||||
}),
|
||||
{
|
||||
status: 400,
|
||||
@@ -33,6 +34,14 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
|
||||
const existingConfig = existingConfigResult[0];
|
||||
|
||||
// Map UI structure to database schema structure first
|
||||
const { githubConfig: mappedGithubConfig, giteaConfig: mappedGiteaConfig } = mapUiToDbConfig(
|
||||
githubConfig,
|
||||
giteaConfig,
|
||||
mirrorOptions,
|
||||
advancedOptions
|
||||
);
|
||||
|
||||
// Preserve tokens if fields are empty
|
||||
if (existingConfig) {
|
||||
try {
|
||||
@@ -46,12 +55,12 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
? JSON.parse(existingConfig.giteaConfig)
|
||||
: existingConfig.giteaConfig;
|
||||
|
||||
if (!githubConfig.token && existingGithub.token) {
|
||||
githubConfig.token = existingGithub.token;
|
||||
if (!mappedGithubConfig.token && existingGithub.token) {
|
||||
mappedGithubConfig.token = existingGithub.token;
|
||||
}
|
||||
|
||||
if (!giteaConfig.token && existingGitea.token) {
|
||||
giteaConfig.token = existingGitea.token;
|
||||
if (!mappedGiteaConfig.token && existingGitea.token) {
|
||||
mappedGiteaConfig.token = existingGitea.token;
|
||||
}
|
||||
} catch (tokenError) {
|
||||
console.error("Failed to preserve tokens:", tokenError);
|
||||
@@ -120,8 +129,8 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
await db
|
||||
.update(configs)
|
||||
.set({
|
||||
githubConfig,
|
||||
giteaConfig,
|
||||
githubConfig: mappedGithubConfig,
|
||||
giteaConfig: mappedGiteaConfig,
|
||||
scheduleConfig: processedScheduleConfig,
|
||||
cleanupConfig: processedCleanupConfig,
|
||||
updatedAt: new Date(),
|
||||
@@ -168,8 +177,8 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
userId,
|
||||
name: "Default Configuration",
|
||||
isActive: true,
|
||||
githubConfig,
|
||||
giteaConfig,
|
||||
githubConfig: mappedGithubConfig,
|
||||
giteaConfig: mappedGiteaConfig,
|
||||
include: [],
|
||||
exclude: [],
|
||||
scheduleConfig: processedScheduleConfig,
|
||||
@@ -214,33 +223,40 @@ export const GET: APIRoute = async ({ request }) => {
|
||||
.limit(1);
|
||||
|
||||
if (config.length === 0) {
|
||||
// Return a default empty configuration instead of a 404 error
|
||||
// Return a default empty configuration with UI structure
|
||||
const defaultDbConfig = {
|
||||
githubConfig: {
|
||||
username: "",
|
||||
token: "",
|
||||
skipForks: false,
|
||||
privateRepositories: false,
|
||||
mirrorIssues: false,
|
||||
mirrorWiki: false,
|
||||
mirrorStarred: false,
|
||||
useSpecificUser: false,
|
||||
preserveOrgStructure: false,
|
||||
skipStarredIssues: false,
|
||||
},
|
||||
giteaConfig: {
|
||||
url: "",
|
||||
token: "",
|
||||
username: "",
|
||||
organization: "github-mirrors",
|
||||
visibility: "public",
|
||||
starredReposOrg: "github",
|
||||
preserveOrgStructure: false,
|
||||
},
|
||||
};
|
||||
|
||||
const uiConfig = mapDbToUiConfig(defaultDbConfig);
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
id: null,
|
||||
userId: userId,
|
||||
name: "Default Configuration",
|
||||
isActive: true,
|
||||
githubConfig: {
|
||||
username: "",
|
||||
token: "",
|
||||
skipForks: false,
|
||||
privateRepositories: false,
|
||||
mirrorIssues: false,
|
||||
mirrorWiki: false,
|
||||
mirrorStarred: true,
|
||||
useSpecificUser: false,
|
||||
preserveOrgStructure: true,
|
||||
skipStarredIssues: false,
|
||||
},
|
||||
giteaConfig: {
|
||||
url: "",
|
||||
token: "",
|
||||
username: "",
|
||||
organization: "github-mirrors",
|
||||
visibility: "public",
|
||||
starredReposOrg: "github",
|
||||
},
|
||||
...uiConfig,
|
||||
scheduleConfig: {
|
||||
enabled: false,
|
||||
interval: 3600,
|
||||
@@ -261,7 +277,14 @@ export const GET: APIRoute = async ({ request }) => {
|
||||
);
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify(config[0]), {
|
||||
// Map database structure to UI structure
|
||||
const dbConfig = config[0];
|
||||
const uiConfig = mapDbToUiConfig(dbConfig);
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
...dbConfig,
|
||||
...uiConfig,
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user