Files
picpeak/backend/src/services/photoResolver.js
T

45 lines
1.7 KiB
JavaScript

const path = require('path');
const { resolveExternalPath } = require('./externalMediaService');
const getStoragePath = () => process.env.STORAGE_PATH || path.join(__dirname, '../../../storage');
/**
* Resolve absolute photo file path based on event + photo origin
* Managed: storage/events/active + photo.path (legacy variants supported)
* External reference: EXTERNAL_MEDIA_ROOT + event.external_path + photo.external_relpath
*/
function resolvePhotoFilePath(event, photo) {
if (!event || !photo) throw new Error('resolvePhotoFilePath requires event and photo');
const mode = (event.source_mode || photo.source_origin || 'managed');
if (mode === 'reference' || photo.source_origin === 'external') {
if (!photo.external_relpath) {
throw new Error('Missing external_relpath for external photo');
}
// Normalize duplicate leaf segments (e.g., event.external_path ends with 'individual'
// and external_relpath starts with 'individual/') to avoid double segment like
// '/external-media/.../individual/individual/file.jpg'
let rel = photo.external_relpath;
try {
const lastSeg = path.basename(event.external_path || '');
const firstSeg = rel.split(path.sep)[0];
if (lastSeg && firstSeg && lastSeg === firstSeg) {
rel = rel.split(path.sep).slice(1).join(path.sep) || '';
}
} catch (_) {
// ignore normalization errors
}
return resolveExternalPath(event, rel);
}
const storagePath = getStoragePath();
if (photo.path && photo.path.startsWith('events/active/')) {
return path.join(storagePath, photo.path);
}
return path.join(storagePath, 'events/active', photo.path || '');
}
module.exports = {
resolvePhotoFilePath,
};