'use server' import { Client, Databases, Storage, ID, Query } from 'node-appwrite'; import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite'; import { revalidatePath } from 'next/cache'; import { SCHEMA_MAP, collectionMap } from '@/lib/schema'; // Using local endpoint and the key we set locally const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'http://localhost/v1'; const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69bedced002971103d13'; const API_KEY = process.env.APPWRITE_API_KEY || 'standard_2350cc147ace39b0e3fb2c42d1447bc00effb4d5e6115cd682b0d215297a3b35b2ce82e312bd35cff1b738d5eb3462c5b28887937acf217eca6c2143aa0bf4e85ab183350db830901edc0d80d17755d1de5524b945d0c4cb11871af8d33df7f7cdbdfea4237dfc8a47e3c71ac79b3e5172834cc09d451d687a3db74e839ec7a7'; export async function createDocumentServer(collectionId: string, data: any) { try { const client = new Client() .setEndpoint(ENDPOINT) .setProject(PROJECT_ID) .setKey(API_KEY); const databases = new Databases(client); for(const key in data) { if(data[key] === 'true') data[key] = true; if(data[key] === 'false') data[key] = false; if(data[key] === '' && typeof data[key] === 'string') delete data[key]; } const doc = await databases.createDocument( APPWRITE_ALMEIRA_CONFIG.databaseId, collectionId, ID.unique(), data ); revalidatePath('/dashboard/[entity]', 'page'); return { success: true, doc }; } catch (error: any) { console.error("Create error:", error); return { success: false, error: error.message }; } } export async function updateDocumentServer(collectionId: string, documentId: string, data: any) { try { const client = new Client().setEndpoint(ENDPOINT).setProject(PROJECT_ID).setKey(API_KEY); const databases = new Databases(client); for(const key in data) { if(data[key] === 'true') data[key] = true; if(data[key] === 'false') data[key] = false; if(data[key] === '' && typeof data[key] === 'string') data[key] = null; // Send null to clear optional strings } const doc = await databases.updateDocument( APPWRITE_ALMEIRA_CONFIG.databaseId, collectionId, documentId, data ); revalidatePath('/dashboard/[entity]', 'page'); return { success: true, doc }; } catch (error: any) { console.error("Update error:", error); return { success: false, error: error.message }; } } export async function deleteDocumentServer(collectionId: string, documentId: string, entityAlias: string) { try { const client = new Client().setEndpoint(ENDPOINT).setProject(PROJECT_ID).setKey(API_KEY); const databases = new Databases(client); // Dynamic Relational Restriction Check // We scan all collections in SCHEMA_MAP to see if any holds a relation to the collection we are trying to delete from for (const [colAlias, fields] of Object.entries(SCHEMA_MAP)) { const referencingFields = fields.filter(f => f.type === 'relation' && f.relationCollection === entityAlias); for (const refField of referencingFields) { const checkColId = collectionMap[colAlias]; if (!checkColId) continue; const list = await databases.listDocuments( APPWRITE_ALMEIRA_CONFIG.databaseId, checkColId, [Query.equal(refField.name, documentId), Query.limit(1)] ); if (list.total > 0) { return { success: false, error: `No se puede eliminar. Existen registros en '${colAlias.replace(/_/g, ' ')}' que dependen de este dato.` }; } } } // No relation found preventing deletion, proceed safely! await databases.deleteDocument( APPWRITE_ALMEIRA_CONFIG.databaseId, collectionId, documentId ); revalidatePath('/dashboard/[entity]', 'page'); return { success: true }; } catch (error: any) { console.error("Delete error:", error); return { success: false, error: error.message }; } } export async function uploadMediaServer(formData: FormData) { try { const client = new Client().setEndpoint(ENDPOINT).setProject(PROJECT_ID).setKey(API_KEY); const databases = new Databases(client); const files = formData.getAll('files') as File[]; if (!files || files.length === 0) throw new Error("No hay archivos para subir"); const manualTitulo = formData.get('titulo') as string; const manualAlt = formData.get('alt_text') as string; const manualDesc = formData.get('descripcion_seo') as string; for (const file of files) { if (!file || file.size === 0) continue; // Native Fetch REST call to upload the file bypassing node-appwrite buffer overload const appwriteFormData = new FormData(); appwriteFormData.append('fileId', 'unique()'); appwriteFormData.append('file', file); const uploadResponse = await fetch(`${ENDPOINT}/storage/buckets/media_bucket/files`, { method: 'POST', headers: { 'X-Appwrite-Project': PROJECT_ID, 'X-Appwrite-Key': API_KEY }, body: appwriteFormData }); if (!uploadResponse.ok) { const errBody = await uploadResponse.text(); throw new Error(`Error subiendo al Bucket: ${errBody}`); } const uploadData = await uploadResponse.json(); // Limpiar el nombre del archivo let cleanName = file.name.replace(/\.[^/.]+$/, ""); cleanName = cleanName.replace(/[-_]/g, ' '); cleanName = cleanName.replace(/[0-9]+$/g, ''); cleanName = cleanName.replace(/\s+/g, ' ').trim(); if (!cleanName) cleanName = 'Multimedia'; await databases.createDocument( APPWRITE_ALMEIRA_CONFIG.databaseId, 'media', ID.unique(), { file_id: uploadData.$id, bucket_id: 'media_bucket', titulo: manualTitulo || cleanName, alt_text: manualAlt || cleanName, descripcion_seo: manualDesc || cleanName, tipo: file.type.startsWith('video') ? 'video' : 'imagen' } ); } revalidatePath('/dashboard/media'); return { success: true }; } catch(error: any) { console.error("Upload Error:", error); return { success: false, error: error.message }; } }