initial commit
This commit is contained in:
37
server/features.mjs
Normal file
37
server/features.mjs
Normal file
@@ -0,0 +1,37 @@
|
||||
import { ApiError } from './errors.mjs';
|
||||
|
||||
const routeNumber = value => typeof value === 'string' ? value.replace(/[\s№]/g, '').toLocaleUpperCase('ru') : '';
|
||||
const positive = value => Number.isSafeInteger(Number(value)) && Number(value) > 0;
|
||||
|
||||
export function normalizeAlerts(raw, cityId) {
|
||||
if (!Array.isArray(raw)) throw new ApiError(502);
|
||||
const seen = new Set();
|
||||
return raw.flatMap(alert => {
|
||||
if (!alert || !positive(alert.id)) throw new ApiError(502);
|
||||
if (alert.is_active === false || (alert.city_id != null && Number(alert.city_id) !== cityId) || seen.has(Number(alert.id))) return [];
|
||||
if ((alert.route_numbers != null && (!Array.isArray(alert.route_numbers) || alert.route_numbers.some(value => !routeNumber(value))))
|
||||
|| (alert.route_ids != null && (!Array.isArray(alert.route_ids) || alert.route_ids.some(value => !positive(value))))) throw new ApiError(502);
|
||||
const numbers = Array.isArray(alert.route_numbers) ? alert.route_numbers.map(routeNumber).filter(Boolean) : [];
|
||||
const ids = Array.isArray(alert.route_ids) ? alert.route_ids.filter(positive).map(Number) : [];
|
||||
if (!numbers.length && routeNumber(alert.route_number)) numbers.push(routeNumber(alert.route_number));
|
||||
if (!ids.length && positive(alert.route_id)) ids.push(Number(alert.route_id));
|
||||
const startTime = Date.parse(alert.start_time);
|
||||
const endTime = alert.end_time == null ? null : Date.parse(alert.end_time);
|
||||
if (!Number.isFinite(startTime) || (endTime !== null && !Number.isFinite(endTime)) || typeof alert.title !== 'string' || typeof alert.message !== 'string') throw new ApiError(502);
|
||||
seen.add(Number(alert.id));
|
||||
return [{ id: Number(alert.id), cityId, title: alert.title.trim(), message: alert.message.trim(),
|
||||
type: ['cancellation', 'delay', 'detour'].includes(alert.alert_type) ? alert.alert_type : 'info',
|
||||
routeNumbers: [...new Set(numbers)].sort((a, b) => a.localeCompare(b, 'ru', { numeric: true })), routeIds: [...new Set(ids)], isCityWide: !numbers.length && !ids.length,
|
||||
startTime: new Date(startTime).toISOString(), endTime: endTime === null ? null : new Date(endTime).toISOString() }];
|
||||
});
|
||||
}
|
||||
|
||||
export function normalizeNearby(raw) {
|
||||
if (!Array.isArray(raw)) throw new ApiError(502);
|
||||
return raw.map(stop => {
|
||||
const distance = Number(stop?.distance_meters);
|
||||
if (!stop || !positive(stop.id) || typeof stop.name !== 'string' || !stop.name.trim() || stop.distance_meters == null || !Number.isFinite(distance) || distance < 0) throw new ApiError(502);
|
||||
return { id: Number(stop.id), name: stop.name.trim(), direction: typeof stop.description === 'string' ? stop.description.trim() : '',
|
||||
routesCount: Number(stop.routes_count) || 0, distance: Math.round(distance) };
|
||||
}).sort((a, b) => a.distance - b.distance);
|
||||
}
|
||||
Reference in New Issue
Block a user