Files
harbor-net/src/web/features/diagnostics/connectivityResult.ts
T
dokril 6381760b27
Build and Deploy Gateway / build-and-push (push) Successful in 20s
Build and Deploy Gateway / deploy (push) Successful in 13s
Add network identity diagnostics
2026-08-11 16:19:23 +03:00

120 lines
4.0 KiB
TypeScript

export type DiagnosticSiteStatus = 'available' | 'responded' | 'unavailable';
export interface DiagnosticIpResult extends Record<string, unknown> {
source: string;
address: string | null;
}
export interface DiagnosticSiteResult extends Record<string, unknown> {
id: string;
status: DiagnosticSiteStatus;
httpStatus: number | null;
latencyMs: number | null;
}
export interface DiagnosticNetworkResult extends Record<string, unknown> {
address: string | null;
asn: string | null;
provider: string | null;
city: string | null;
country: string | null;
}
export interface DiagnosticServer extends Record<string, unknown> {
id: string;
label: string;
}
export interface DiagnosticPath extends Record<string, unknown> {
available: boolean;
internetAvailable: boolean;
ipv4: {
addresses: string[];
sources: DiagnosticIpResult[];
};
ipv6: string | null;
ipv6Source: DiagnosticIpResult | null;
network?: DiagnosticNetworkResult | null;
sites: DiagnosticSiteResult[];
server?: DiagnosticServer | null;
}
export interface ConnectivityResult extends Record<string, unknown> {
direct: DiagnosticPath;
vpn: DiagnosticPath & { server: DiagnosticServer | null };
}
function record(value: unknown): value is Record<string, unknown> {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
}
function nullableNonnegativeNumber(value: unknown): value is number | null {
return value === null || (typeof value === 'number' && Number.isFinite(value) && value >= 0);
}
function validIpResult(value: unknown): value is DiagnosticIpResult {
return record(value)
&& typeof value.source === 'string'
&& value.source.length > 0
&& (value.address === null || (typeof value.address === 'string' && value.address.length > 0));
}
function validSiteResult(value: unknown): value is DiagnosticSiteResult {
return record(value)
&& typeof value.id === 'string'
&& value.id.length > 0
&& (value.status === 'available' || value.status === 'responded' || value.status === 'unavailable')
&& nullableNonnegativeNumber(value.httpStatus)
&& nullableNonnegativeNumber(value.latencyMs);
}
function nullableText(value: unknown): value is string | null {
return value === null || (typeof value === 'string' && value.length > 0);
}
function validNetworkResult(value: unknown): value is DiagnosticNetworkResult {
return record(value)
&& nullableText(value.address)
&& nullableText(value.asn)
&& nullableText(value.provider)
&& nullableText(value.city)
&& nullableText(value.country);
}
function validServer(value: unknown): value is DiagnosticServer | null {
return value === null || (record(value)
&& typeof value.id === 'string'
&& typeof value.label === 'string');
}
function validPath(value: unknown): value is DiagnosticPath {
return record(value)
&& typeof value.available === 'boolean'
&& typeof value.internetAvailable === 'boolean'
&& record(value.ipv4)
&& Array.isArray(value.ipv4.addresses)
&& value.ipv4.addresses.every((address) => typeof address === 'string' && address.length > 0)
&& Array.isArray(value.ipv4.sources)
&& value.ipv4.sources.every(validIpResult)
&& (value.ipv6 === null || (typeof value.ipv6 === 'string' && value.ipv6.length > 0))
&& (value.ipv6Source === null || validIpResult(value.ipv6Source))
&& (!Object.hasOwn(value, 'network') || value.network === null || validNetworkResult(value.network))
&& Array.isArray(value.sites)
&& value.sites.every(validSiteResult);
}
function assertConnectivityResult(value: unknown): asserts value is ConnectivityResult {
if (!record(value)
|| !validPath(value.direct)
|| !validPath(value.vpn)
|| !Object.hasOwn(value.vpn, 'server')
|| !validServer(value.vpn.server)) {
throw new TypeError('Harbor connectivity diagnostics returned an invalid result');
}
}
export function parseConnectivityResult(value: unknown): ConnectivityResult {
assertConnectivityResult(value);
return value;
}