import{useTimeAgo}from"@vueuse/core";/**
* Formats ISO timestamp to display format (HH:MM:SS.mmm)
* @param time ISO timestamp to format
* @param showDate Whether to show the date
* @returns Formatted date and time as a string
*/exportfunctionformatTimestamp(time: string,showDate: boolean=false,):string{if(!time)return"";constdate=newDate(time);if(isNaN(date.getTime()))returntime;consthours=date.getHours().toString().padStart(2,"0");constminutes=date.getMinutes().toString().padStart(2,"0");constseconds=date.getSeconds().toString().padStart(2,"0");constms=date.getMilliseconds().toString().padStart(3,"0");consttimeStr=`${hours}:${minutes}:${seconds}.${ms}`;if(showDate){constyear=date.getFullYear();constmonth=(date.getMonth()+1).toString().padStart(2,"0");constday=date.getDate().toString().padStart(2,"0");return`${year}-${month}-${day}${timeStr}`;}returntimeStr;}exportfunctionformatLocalNumber(number:number|undefined):string{if(!number)return"0";returnnumber.toLocaleString();}/**
* Formats a date and time for local display using toLocaleString()
* @param time Date and time to format
* @returns Formatted date and time as a string
*/exportfunctionformatLocalDateTime(time: string,noSec: boolean=false,):string{if(!time)return"";constdate=newDate(time);if(isNaN(date.getTime()))returntime;if(noSec){returndate.toLocaleString([],{day:"2-digit",month:"2-digit",year:"2-digit",hour:"2-digit",minute:"2-digit",});}returndate.toLocaleString();}/**
* Formats a date and time for API use (YYYY-MM-DD HH:MM:SS.mmm)
* @param time Date and time to format
* @returns Formatted date and time as a string
*/exportfunctionformatDateTimeForAPI(time: string):string{if(!time)return"";constd=newDate(time);if(isNaN(d.getTime()))returntime.replace("T"," ")+":00";returnd.toISOString();}/**
* Formats a date for datetime-local input (YYYY-MM-DDTHH:mm)
* @param time Date and time to format
* @returns Formatted date and time as a string
*/exportfunctionformatDateForInput(time: string):string{if(!time)return"";constd=newDate(time);if(isNaN(d.getTime()))return"";constyear=d.getFullYear();constmonth=(d.getMonth()+1).toString().padStart(2,"0");constday=d.getDate().toString().padStart(2,"0");consthours=d.getHours().toString().padStart(2,"0");constminutes=d.getMinutes().toString().padStart(2,"0");return`${year}-${month}-${day}T${hours}:${minutes}`;}/**
* Formats a JSON object for display in a HTML span
* @param json JSON object to format
* @param indent Number of spaces to indent the JSON object
* @returns Formatted JSON object as a string
*/exportfunctionformatJsonForDisplay(json: any,indent: number=0):string{constindentSpace=(n: number)=>" ".repeat(n);functionisPlainObject(obj: any){returnObject.prototype.toString.call(obj)==="[object Object]";}functionescapeHtml(str: string):string{returnstr.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'");}functionvalueToHtml(val: any,depth: number):string{if(val===null){return`<span class="v-null">null</span>`;}if(typeofval==="string"){return`<span class="v-str">${escapeHtml(val)}</span>`;}if(typeofval==="number"){return`<span class="v-num">${escapeHtml(val.toString())}</span>`;}if(typeofval==="boolean"){return`<span class="v-bool">${escapeHtml(val.toString())}</span>`;}if(Array.isArray(val)){if(val.length===0)return`<span class="v-arr">[]</span>`;returnval.map((item)=>`${indentSpace(depth+1)}- ${valueToHtml(item,depth+1)}`,).join("\n");}if(isPlainObject(val)){constkeys=Object.keys(val);if(keys.length===0)return`<span class="v-obj">{}</span>`;returnkeys.map((k)=>{letvalueHtml=valueToHtml(val[k],depth+1);// If the value is an object, array, or otherwise multi-line, add a newline after the key
if((isPlainObject(val[k])&&Object.keys(val[k]).length>0)||(Array.isArray(val[k])&&val[k].length>0)){return`${indentSpace(depth)}<span class="k">${escapeHtml(k)}</span>:\n${valueHtml}`;}else{return`${indentSpace(depth)}<span class="k">${escapeHtml(k)}</span>: ${valueHtml}`;}}).join("\n");}return`<span class="v-unk">${escapeHtml(String(val))}</span>`;}returnvalueToHtml(json,indent);}/**
* Converts an IP address to an integer for color mapping
* @param ip IP address to convert to integer
* @returns Integer representation of the IP address
*/exportfunctionipToInt(ip: string):number{constparts=ip.split(".");if(parts.length!==4)return0;constp0=parseInt(parts[0]||"0");constp1=parseInt(parts[1]||"0");constp2=parseInt(parts[2]||"0");constp3=parseInt(parts[3]||"0");returnp0*16777216+p1*65536+p2*256+p3;}/**
* Converts an integer back to an IP address string
* @param int Integer representation of the IP address
* @returns IP address string
*/functionintToIp(int: number):string{return[(int>>>24)&0xff,(int>>>16)&0xff,(int>>>8)&0xff,int&0xff,].join(".");}/**
* Masks an IP address with a given number of mask bits
* @param ip IP address string
* @param maskBits Number of mask bits
* @returns Masked IP address string
*/exportfunctionmaskIp(ip: string,maskBits: number):string{constint=ipToInt(ip);constmask=maskBits===0?0:(~0<<(32-maskBits))>>>0;returnintToIp((int&mask)>>>0);}exportfunctiontimeAgo(time: string|undefined):string{if(!time)return"N/A";returnuseTimeAgo(newDate(time)).value;}/**
* Splits a label into address and mask if it's a CIDR subnet
* @param label The label to split
* @returns Object with address and mask
*/exportfunctionsplitSubnet(label: string|number):{address: string;mask: string;}{conststr=String(label);constmatch=str.match(/^(.+)(\/\d+)$/);if(match){return{address: match[1]asstring,mask: match[2]asstring};}return{address: str,mask:""};}