Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m46s
132 lines
4.1 KiB
JavaScript
132 lines
4.1 KiB
JavaScript
/**
|
|
* Общие утилиты для работы с серверами и шлюзами
|
|
* Используется в ServerManager, FilterManager и других компонентах
|
|
*/
|
|
|
|
/**
|
|
* Создаёт объект шлюза с дефолтными значениями
|
|
* @param {Object} overrides - Переопределяемые поля
|
|
* @returns {Object} Объект шлюза
|
|
*/
|
|
export const makeGateway = (overrides = {}) => ({
|
|
id: `${Date.now()}-${Math.random().toString(16).slice(2, 8)}`,
|
|
name: '',
|
|
ip: '',
|
|
comment: '',
|
|
primary: false,
|
|
...overrides,
|
|
});
|
|
|
|
/**
|
|
* Нормализует массив шлюзов: очищает, удаляет пустые, гарантирует один primary
|
|
* @param {Array} gateways - Массив шлюзов
|
|
* @param {string} fallbackName - Имя по умолчанию если массив пуст
|
|
* @returns {Array} Нормализованный массив шлюзов
|
|
*/
|
|
export const normalizeGateways = (gateways = [], fallbackName = '') => {
|
|
if (!Array.isArray(gateways)) return [];
|
|
|
|
const cleaned = gateways
|
|
.map((g, idx) => ({
|
|
id: g?.id || `${Date.now()}-${idx}`,
|
|
name: String(g?.name || '').trim(),
|
|
ip: String(g?.ip || '').trim(),
|
|
comment: String(g?.comment || '').trim(),
|
|
primary: Boolean(g?.primary),
|
|
}))
|
|
.filter(g => g.name || g.ip || g.comment);
|
|
|
|
if (cleaned.length === 0) {
|
|
return [{
|
|
id: `${Date.now()}-primary`,
|
|
name: fallbackName || 'gateway',
|
|
ip: '',
|
|
comment: '',
|
|
primary: true
|
|
}];
|
|
}
|
|
|
|
// Гарантируем только один primary
|
|
let hasPrimary = false;
|
|
cleaned.forEach((g) => {
|
|
if (g.primary && !hasPrimary) {
|
|
hasPrimary = true;
|
|
} else {
|
|
g.primary = false;
|
|
}
|
|
});
|
|
|
|
if (!hasPrimary) {
|
|
cleaned[0].primary = true;
|
|
}
|
|
|
|
return cleaned;
|
|
};
|
|
|
|
/**
|
|
* Конвертирует код страны в эмодзи флага
|
|
* @param {string} code - Двухбуквенный код страны (ISO 3166-1 alpha-2)
|
|
* @returns {string} Эмодзи флага или пустая строка
|
|
*/
|
|
export const countryToFlag = (code) => {
|
|
if (!code || typeof code !== 'string') return '';
|
|
const cc = code.trim().toUpperCase();
|
|
if (cc.length !== 2) return '';
|
|
const codePoints = [...cc].map((c) => 0x1f1e6 - 65 + c.charCodeAt(0));
|
|
return String.fromCodePoint(...codePoints);
|
|
};
|
|
|
|
/**
|
|
* Проверяет, требует ли тип сервера наличие шлюзов
|
|
* @param {string} type - Тип сервера
|
|
* @returns {boolean}
|
|
*/
|
|
export const needsGateways = (type) => {
|
|
return ['jumphost', 'exit'].includes(String(type || '').toLowerCase());
|
|
};
|
|
|
|
/**
|
|
* Константы типов серверов
|
|
*/
|
|
export const SERVER_TYPE_OPTIONS = [
|
|
{ value: 'jumphost', label: 'Jumphost' },
|
|
{ value: 'exit', label: 'Выходная нода' },
|
|
];
|
|
|
|
/**
|
|
* Типы туннелей
|
|
*/
|
|
export const TUNNEL_TYPES = ['GRE', 'IPSec', 'WireGuard', 'VXLAN', 'OpenVPN'];
|
|
|
|
/**
|
|
* Генерирует уникальный ID
|
|
* @returns {string}
|
|
*/
|
|
export const generateId = () => {
|
|
return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
};
|
|
|
|
/**
|
|
* Нормализует community value (добавляет ASN если отсутствует)
|
|
* @param {string} value - Значение community
|
|
* @param {string} defaultASN - ASN по умолчанию
|
|
* @returns {string}
|
|
*/
|
|
export const normalizeCommunityValue = (value, defaultASN = '65001') => {
|
|
const trimmed = String(value || '').trim();
|
|
if (!trimmed) return '';
|
|
return trimmed.includes(':') ? trimmed : `${defaultASN}:${trimmed}`;
|
|
};
|
|
|
|
/**
|
|
* Извлекает короткую часть community (после двоеточия)
|
|
* @param {string} value - Полное значение community (например "65000:120")
|
|
* @returns {string} Короткая часть (например "120")
|
|
*/
|
|
export const getShortCommunityValue = (value) => {
|
|
const str = String(value || '').trim();
|
|
if (!str.includes(':')) return str;
|
|
return str.split(':')[1] || str;
|
|
};
|
|
|