fix: resolve 'Only plain objects' serialization errors across dashboard and home

- Applied JSON.parse(JSON.stringify()) sanitization to documents and relationData in EditEntityPage.
- Sanitized relationData and user in NewEntityPage.
- Sanitized posts and settings in Homepage.
- Added missing Query import to dashboard edit page.
- This ensures all data passed to Client Components is in a serializable POJO format.
This commit is contained in:
Carlos (Almeira) 2026-03-28 12:05:41 -05:00
parent c6cb9a0265
commit b58a2a59fb
3 changed files with 12 additions and 11 deletions

View File

@ -1,5 +1,6 @@
import { APPWRITE_ALMEIRA_CONFIG, projectId, endpoint } from '@/lib/appwrite'; import { APPWRITE_ALMEIRA_CONFIG, projectId, endpoint } from '@/lib/appwrite';
import { createSessionClient, getLoggedInUser } from '@/lib/appwrite.server'; import { createSessionClient, getLoggedInUser } from '@/lib/appwrite.server';
import { Query } from 'node-appwrite';
import { collectionMap, SCHEMA_MAP } from '@/lib/schema'; import { collectionMap, SCHEMA_MAP } from '@/lib/schema';
import { updateDocumentServer } from '@/app/actions/appwrite'; import { updateDocumentServer } from '@/app/actions/appwrite';
import { updateEntityAction } from '@/app/actions/entities'; import { updateEntityAction } from '@/app/actions/entities';
@ -27,7 +28,7 @@ export default async function EditEntityPage({ params }: { params: Promise<{ ent
} }
const sessionClient = await createSessionClient(); const sessionClient = await createSessionClient();
const user = await getLoggedInUser(); const user = JSON.parse(JSON.stringify(await getLoggedInUser()));
if (!sessionClient || !user) { if (!sessionClient || !user) {
redirect('/login'); redirect('/login');
} }
@ -35,11 +36,11 @@ export default async function EditEntityPage({ params }: { params: Promise<{ ent
// Fetch the existing document // Fetch the existing document
let document: any = null; let document: any = null;
try { try {
document = await sessionClient.databases.getDocument( document = JSON.parse(JSON.stringify(await sessionClient.databases.getDocument(
APPWRITE_ALMEIRA_CONFIG.databaseId, APPWRITE_ALMEIRA_CONFIG.databaseId,
collectionId, collectionId,
id id
); )));
} catch (e) { } catch (e) {
return ( return (
<div className="p-8"> <div className="p-8">
@ -55,8 +56,8 @@ export default async function EditEntityPage({ params }: { params: Promise<{ ent
try { try {
const relKey = field.relationCollection as string; const relKey = field.relationCollection as string;
if(!collectionMap[relKey]) return; if(!collectionMap[relKey]) return;
const res = await sessionClient.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, collectionMap[relKey], []); const res = await sessionClient.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, collectionMap[relKey], [Query.limit(100)]);
relationData[field.name] = res.documents; relationData[field.name] = JSON.parse(JSON.stringify(res.documents));
} catch(e) { console.error('Error obteniendo relaciones de', field.name, e); } } catch(e) { console.error('Error obteniendo relaciones de', field.name, e); }
}) })
); );

View File

@ -29,7 +29,7 @@ export default async function NewEntityPage({
} }
// Auth check // Auth check
const user = await getLoggedInUser(); const user = JSON.parse(JSON.stringify(await getLoggedInUser()));
if (!user) redirect('/login'); if (!user) redirect('/login');
// Pre-load all relation data server-side // Pre-load all relation data server-side
@ -49,7 +49,7 @@ export default async function NewEntityPage({
relColId, relColId,
[Query.limit(100)] [Query.limit(100)]
); );
relationData[field.name] = res.documents as Array<{ $id: string; [key: string]: unknown }>; relationData[field.name] = JSON.parse(JSON.stringify(res.documents));
} catch { } catch {
// Silent fail for individual relations // Silent fail for individual relations
} }

View File

@ -15,12 +15,12 @@ async function fetchHomeData() {
// 1. Settings // 1. Settings
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []); const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : { const settings = JSON.parse(JSON.stringify(settingsRes.documents.length > 0 ? settingsRes.documents[0] : {
ticker_count: 10, ticker_count: 10,
rotation_seconds: 5, rotation_seconds: 5,
feed_news_count: 12, feed_news_count: 12,
show_news_date: true show_news_date: true
}) as Settings; })) as Settings;
const postsCount = settings.feed_news_count || 12; const postsCount = settings.feed_news_count || 12;
const cardSettings = { const cardSettings = {
@ -55,10 +55,10 @@ async function fetchHomeData() {
Query.equal('$id', mediaIds) Query.equal('$id', mediaIds)
]); ]);
const mediaMap = new Map<string, MediaItem>(mediaRes.documents.map(m => [m.$id, m as unknown as MediaItem])); const mediaMap = new Map<string, MediaItem>(mediaRes.documents.map(m => [m.$id, m as unknown as MediaItem]));
posts = posts.map(p => ({ posts = posts.map(p => JSON.parse(JSON.stringify({
...p, ...p,
resolved_media: mediaMap.get(p.imagen_destacada_id as string) resolved_media: mediaMap.get(p.imagen_destacada_id as string)
})); })));
} }
} }