fix contrib mechanic

This commit is contained in:
overcuriousity
2025-08-10 23:00:01 +02:00
parent 2fcc84991a
commit 4cc3e2c830
7 changed files with 1147 additions and 244 deletions

View File

@@ -1,4 +1,4 @@
// src/pages/api/contribute/tool.ts (UPDATED - Using consolidated API responses)
// src/pages/api/contribute/tool.ts (UPDATED - Using consolidated API responses + related_software)
import type { APIRoute } from 'astro';
import { withAPIAuth } from '../../../utils/auth.js';
import { apiResponse, apiError, apiServerError, apiSpecial, handleAPIRequest } from '../../../utils/api.js';
@@ -27,6 +27,7 @@ const ContributionToolSchema = z.object({
knowledgebase: z.boolean().optional().nullable(),
'domain-agnostic-software': z.array(z.string()).optional().nullable(),
related_concepts: z.array(z.string()).optional().nullable(),
related_software: z.array(z.string()).optional().nullable(),
tags: z.array(z.string()).default([]),
statusUrl: z.string().url('Must be a valid URL').optional().nullable()
});
@@ -80,6 +81,38 @@ function sanitizeInput(obj: any): any {
return obj;
}
function preprocessFormData(body: any): any {
// Handle comma-separated strings from autocomplete inputs
if (body.tool) {
// Handle tags
if (typeof body.tool.tags === 'string') {
body.tool.tags = body.tool.tags.split(',').map((t: string) => t.trim()).filter(Boolean);
}
// Handle related concepts
if (body.tool.relatedConcepts) {
if (typeof body.tool.relatedConcepts === 'string') {
body.tool.related_concepts = body.tool.relatedConcepts.split(',').map((t: string) => t.trim()).filter(Boolean);
} else {
body.tool.related_concepts = body.tool.relatedConcepts;
}
delete body.tool.relatedConcepts; // Remove the original key
}
// Handle related software
if (body.tool.relatedSoftware) {
if (typeof body.tool.relatedSoftware === 'string') {
body.tool.related_software = body.tool.relatedSoftware.split(',').map((t: string) => t.trim()).filter(Boolean);
} else {
body.tool.related_software = body.tool.relatedSoftware;
}
delete body.tool.relatedSoftware; // Remove the original key
}
}
return body;
}
async function validateToolData(tool: any, action: string): Promise<{ valid: boolean; errors: string[] }> {
const errors: string[] = [];
@@ -109,6 +142,17 @@ async function validateToolData(tool: any, action: string): Promise<{ valid: boo
}
}
// Validate related items exist (optional validation - could be enhanced)
if (tool.related_concepts && tool.related_concepts.length > 0) {
// Could validate that referenced concepts actually exist
console.log('[VALIDATION] Related concepts provided:', tool.related_concepts);
}
if (tool.related_software && tool.related_software.length > 0) {
// Could validate that referenced software actually exists
console.log('[VALIDATION] Related software provided:', tool.related_software);
}
return { valid: errors.length === 0, errors };
} catch (error) {
@@ -143,6 +187,9 @@ export const POST: APIRoute = async ({ request }) => {
return apiSpecial.invalidJSON();
}
// Preprocess form data to handle autocomplete inputs
body = preprocessFormData(body);
const sanitizedBody = sanitizeInput(body);
let validatedData;
@@ -153,6 +200,7 @@ export const POST: APIRoute = async ({ request }) => {
const errorMessages = error.errors.map(err =>
`${err.path.join('.')}: ${err.message}`
);
console.log('[VALIDATION] Zod validation errors:', errorMessages);
return apiError.validation('Validation failed', errorMessages);
}
@@ -174,6 +222,16 @@ export const POST: APIRoute = async ({ request }) => {
}
};
console.log('[CONTRIBUTION] Processing contribution:', {
type: contributionData.type,
toolName: contributionData.tool.name,
toolType: contributionData.tool.type,
submitter: userEmail,
hasRelatedConcepts: !!(contributionData.tool.related_concepts?.length),
hasRelatedSoftware: !!(contributionData.tool.related_software?.length),
tagsCount: contributionData.tool.tags?.length || 0
});
try {
const gitManager = new GitContributionManager();
const result = await gitManager.submitContribution(contributionData);