/** * Helpers pour la manipulation de données Firestore */ const admin = require('firebase-admin'); /** * Convertit les Timestamps Firestore en ISO strings pour JSON */ function serializeTimestamps(data) { if (!data) return data; const result = { ...data }; for (const key in result) { if (result[key] && result[key].toDate && typeof result[key].toDate === 'function') { // C'est un Timestamp Firestore result[key] = result[key].toDate().toISOString(); } else if (result[key] && typeof result[key] === 'object' && !Array.isArray(result[key])) { // Objet imbriqué result[key] = serializeTimestamps(result[key]); } else if (Array.isArray(result[key])) { // Tableau result[key] = result[key].map(item => item && typeof item === 'object' ? serializeTimestamps(item) : item ); } } return result; } /** * Convertit les ISO strings en Timestamps Firestore */ function deserializeTimestamps(data, timestampFields = []) { if (!data) return data; const result = { ...data }; for (const field of timestampFields) { if (result[field] && typeof result[field] === 'string') { result[field] = admin.firestore.Timestamp.fromDate(new Date(result[field])); } } return result; } /** * Convertit les références DocumentReference en IDs */ function serializeReferences(data) { if (!data) return data; const result = { ...data }; for (const key in result) { if (result[key] && result[key].path && typeof result[key].path === 'string') { // C'est une DocumentReference result[key] = result[key].id; } else if (Array.isArray(result[key])) { result[key] = result[key].map(item => { if (item && item.path && typeof item.path === 'string') { return item.id; } return item; }); } } return result; } /** * Masque les champs sensibles selon les permissions */ function maskSensitiveFields(data, canViewSensitive) { if (canViewSensitive) return data; const masked = { ...data }; // Masquer les prix si pas de permission manage_equipment delete masked.purchasePrice; delete masked.rentalPrice; return masked; } /** * Pagination helper */ function paginate(query, limit = 50, startAfter = null) { let paginatedQuery = query.limit(limit); if (startAfter) { paginatedQuery = paginatedQuery.startAfter(startAfter); } return paginatedQuery; } /** * Filtre les événements annulés */ function filterCancelledEvents(events) { return events.filter(event => event.status !== 'CANCELLED'); } module.exports = { serializeTimestamps, deserializeTimestamps, serializeReferences, maskSensitiveFields, paginate, filterCancelledEvents, };