blob: 931653f9280b0a3974becda934c89c8d110b109e (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
/* jshint esversion: 2024, module: true */
import { InterfaceState } from "./enums.js";
/**
* Static utility functions
* @module Utils
*/
class Utils {
/**
* Convert byte array to MAC address
* @static
* @param {Array} bytes - Byte array
* @returns {string} MAC address
*/
static arrayToMac(bytes) {
if (!Array.isArray(bytes)) return "";
return bytes.map((byte) => byte.toString(16).padStart(2, "0")).join(":");
}
/**
* Convert byte array to IP address
* @static
* @param {Array|Object} obj - IP data
* @returns {string} IP address
*/
static ipFromArray(obj) {
let bytes = null;
if (Array.isArray(obj)) {
bytes = obj;
} else if (obj?.Address && Array.isArray(obj.Address)) {
bytes = obj.Address;
} else {
return "";
}
// IPv4
if (bytes.length === 4) {
return bytes.join(".");
}
// IPv6
if (bytes.length === 16) {
const parts = [];
for (let i = 0; i < 16; i += 2) {
parts.push(((bytes[i] << 8) | bytes[i + 1]).toString(16));
}
return parts
.join(":")
.replace(/(^|:)0+/g, "$1")
.replace(/:{3,}/, "::");
}
return "";
}
/**
* Convert route object to string
* @static
* @param {Object} route - Route object
* @returns {string} Route string
*/
static routeToString(route) {
if (!route) return "";
const destination = route.Destination
? Utils.ipFromArray(route.Destination)
: "default";
const gateway = route.Gateway ? Utils.ipFromArray(route.Gateway) : "";
return gateway ? `${destination} → ${gateway}` : destination;
}
/**
* Get interface state from interface object
* @static
* @param {Object} iface - Interface object
* @returns {Symbol} Interface state
*/
static getInterfaceState(iface) {
const state =
iface.OperationalState ?? iface.AdministrativeState ?? iface.State ?? "";
const stateLower = state.toLowerCase();
if (
stateLower.includes("up") ||
stateLower.includes("routable") ||
stateLower.includes("configured")
) {
return InterfaceState.UP;
} else if (stateLower.includes("down") || stateLower.includes("off")) {
return InterfaceState.DOWN;
} else {
return InterfaceState.UNKNOWN;
}
}
/**
* Get CSS class for interface state
* @static
* @param {Symbol} state - Interface state
* @returns {string} CSS class
*/
static getStateClass(state) {
switch (state) {
case InterfaceState.UP:
return "state-up";
case InterfaceState.DOWN:
return "state-down";
default:
return "state-unknown";
}
}
/**
* Get display text for interface state
* @static
* @param {Object} iface - Interface object
* @returns {string} State text
*/
static getStateText(iface) {
return (
iface.OperationalState ??
iface.AdministrativeState ??
iface.State ??
"unknown"
);
}
/**
* Sanitize HTML string
* @static
* @param {string} str - String to sanitize
* @returns {string} Sanitized string
*/
static sanitizeHTML(str) {
const div = document.createElement("div");
div.textContent = str;
return div.innerHTML;
}
/**
* Create DOM element from HTML string
* @static
* @param {string} html - HTML string
* @returns {HTMLElement} DOM element
*/
static createElementFromHTML(html) {
const template = document.createElement("template");
template.innerHTML = html.trim();
return template.content.firstElementChild;
}
/**
* Debounce function
* @static
* @param {Function} func - Function to debounce
* @param {number} wait - Wait time in ms
* @returns {Function} Debounced function
*/
static debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* Safely convert any value to display string
* @static
* @param {*} value - Any value
* @returns {string} Safe display string
*/
static safeToString(value) {
if (value === null || value === undefined) return "";
if (typeof value === "string") return value;
if (typeof value === "number" || typeof value === "boolean")
return String(value);
if (Array.isArray(value)) {
return value.map((item) => Utils.safeToString(item)).join(", ");
}
if (typeof value === "object") {
// Handle IP address objects
if (value.Address && Array.isArray(value.Address)) {
return Utils.ipFromArray(value);
}
// Try to stringify simple objects
try {
const simpleObj = {};
for (const [key, val] of Object.entries(value)) {
if (val !== null && val !== undefined && typeof val !== "object") {
simpleObj[key] = val;
}
}
if (Object.keys(simpleObj).length > 0) {
return JSON.stringify(simpleObj);
}
} catch (e) {
// Fall through
}
return String(value);
}
return String(value);
}
}
export { Utils };
|