Enhance FaceAI integration with live checks and metadata handling
All checks were successful
Publish FaceAI Container / publish (push) Successful in 3m22s

- Added optional live FaceAI checks in README.md
- Implemented relative storage segment parsing in race-storage.js
- Updated server.js to include relative directory in race storage
- Refactored legacyAssets.js to resolve asset base URL dynamically
- Expanded live race tests to validate FaceAI app launch and metadata
- Introduced portrait image handling for live upload flow
- Updated faceai_handoff.php to process race storage relative directory
This commit is contained in:
MaddoScientisto 2026-04-19 10:38:32 +02:00
commit bb60201ad4
9 changed files with 214 additions and 25 deletions

View file

@ -30,6 +30,20 @@ function sanitizePathSegment(value) {
return normalized;
}
function parseRelativeStorageSegments(value) {
const normalized = String(value || '').trim().replace(/\\/g, '/');
if (!normalized) {
return [];
}
return normalized
.split('/')
.map((segment) => segment.trim())
.filter(Boolean)
.map((segment) => sanitizePathSegment(segment));
}
export function normalizeRaceFolderName(value) {
return String(value || '')
.trim()
@ -49,9 +63,16 @@ export function buildMonthFolder(year, monthIndex) {
}
export function buildRaceStorage(storageInput = {}) {
const year = sanitizePathSegment(storageInput.year);
const monthFolder = sanitizePathSegment(storageInput.monthFolder);
const raceFolder = sanitizePathSegment(normalizeRaceFolderName(storageInput.raceFolder));
const relativeSegments = parseRelativeStorageSegments(storageInput.relativeDir);
const relativeYear = relativeSegments[0] || '';
const relativeMonthFolder = relativeSegments.length >= 3 ? relativeSegments[1] : '';
const relativeRaceFolder = relativeSegments.length >= 3
? relativeSegments[2]
: (relativeSegments.length >= 2 ? relativeSegments[1] : '');
const year = sanitizePathSegment(storageInput.year || relativeYear);
const monthFolder = sanitizePathSegment(storageInput.monthFolder || relativeMonthFolder);
const raceFolder = sanitizePathSegment(normalizeRaceFolderName(storageInput.raceFolder || relativeRaceFolder));
if (!year || !monthFolder || !raceFolder) {
return null;

View file

@ -262,7 +262,8 @@ app.get('/dev/legacy/launch', (req, res) => {
raceStorage: {
year: String(req.query.raceYear || mockCatalog[raceId]?.storage?.year || ''),
monthFolder: String(req.query.raceMonthFolder || mockCatalog[raceId]?.storage?.monthFolder || ''),
raceFolder: String(req.query.raceFolder || mockCatalog[raceId]?.storage?.raceFolder || '')
raceFolder: String(req.query.raceFolder || mockCatalog[raceId]?.storage?.raceFolder || ''),
relativeDir: String(req.query.raceStorageRelativeDir || '')
},
lang,
returnUrl

View file

@ -1,4 +1,33 @@
const legacyAssetBaseUrl = (import.meta.env.VITE_LEGACY_ASSET_BASE_URL || '/legacy-static').replace(/\/$/, '');
import { getLegacyBaseUrl } from './legacyUrls.js';
const localHostnames = new Set(['localhost', '127.0.0.1', '::1']);
function trimTrailingSlash(value) {
return String(value || '').replace(/\/$/, '');
}
function currentHostname() {
if (typeof window === 'undefined' || !window.location || !window.location.hostname) {
return '';
}
return window.location.hostname.toLowerCase();
}
function resolveLegacyAssetBaseUrl() {
const configuredAssetBaseUrl = trimTrailingSlash(import.meta.env.VITE_LEGACY_ASSET_BASE_URL || '');
if (configuredAssetBaseUrl) {
return configuredAssetBaseUrl;
}
if (localHostnames.has(currentHostname())) {
return '/legacy-static';
}
return getLegacyBaseUrl();
}
const legacyAssetBaseUrl = resolveLegacyAssetBaseUrl();
export function legacyAsset(path) {
return `${legacyAssetBaseUrl}${path.startsWith('/') ? path : `/${path}`}`;