mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
74 lines
2.9 KiB
TypeScript
74 lines
2.9 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
export interface SplashDiagnosticsInput {
|
|
readonly generatedAt: number;
|
|
readonly splashOpenedAt: number | null;
|
|
readonly appVersion: string;
|
|
readonly channel: string;
|
|
readonly platform: string;
|
|
readonly arch: string;
|
|
readonly osVersion: string;
|
|
readonly electronVersion: string;
|
|
readonly logsPath: string | null;
|
|
readonly userDataPath: string;
|
|
readonly packageOrigin: string;
|
|
readonly proxyRoute: string | null;
|
|
readonly splashStatus: string | null;
|
|
readonly updaterStatus: string | null;
|
|
readonly pendingModule: string | null;
|
|
readonly receivedBytes: number | null;
|
|
readonly totalBytes: number | null;
|
|
readonly bytesPerSecond: number | null;
|
|
readonly committed: Readonly<Record<string, string>>;
|
|
readonly lastError: string | null;
|
|
readonly lastErrorAt: number | null;
|
|
}
|
|
|
|
const SHA_PREFIX_LENGTH = 12;
|
|
const SECRET_HEADER_PATTERN =
|
|
/\b(authorization|cookie|token|secret|password)\b\s*[:=]\s*(?:(?:bearer|basic)\s+)?[^\s&]+/giu;
|
|
const SECRET_QUERY_PATTERN = /([?&])([^=&#\s]+)=([^&#\s]*)/gu;
|
|
const SECRET_USERINFO_PATTERN = /[^\s:@/]+:[^\s@/]+@/gu;
|
|
|
|
export function redactDiagnosticText(value: string): string {
|
|
return value
|
|
.replace(SECRET_HEADER_PATTERN, (_match, key: string) => `${key}=…`)
|
|
.replace(SECRET_QUERY_PATTERN, (_match, separator: string, key: string) => `${separator}${key}=…`)
|
|
.replace(SECRET_USERINFO_PATTERN, '…@');
|
|
}
|
|
|
|
function formatTime(value: number | null): string {
|
|
return value == null ? 'none' : new Date(value).toISOString();
|
|
}
|
|
|
|
function formatBytes(value: number | null): string {
|
|
return value == null ? 'unknown' : `${value} bytes`;
|
|
}
|
|
|
|
export function buildSplashDiagnosticsText(input: SplashDiagnosticsInput): string {
|
|
const committed = Object.entries(input.committed)
|
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
.map(([name, sha]) => ` ${name} ${sha.slice(0, SHA_PREFIX_LENGTH)}`);
|
|
const lines = [
|
|
'Fluxer desktop updater diagnostics',
|
|
`Generated: ${formatTime(input.generatedAt)}`,
|
|
`Splash opened: ${formatTime(input.splashOpenedAt)}`,
|
|
`App version: ${input.appVersion} (${input.channel})`,
|
|
`Platform: ${input.platform} ${input.arch}, OS ${input.osVersion}, Electron ${input.electronVersion}`,
|
|
`Logs: ${input.logsPath ?? 'unknown'}`,
|
|
`User data: ${input.userDataPath}`,
|
|
`Package origin: ${input.packageOrigin}`,
|
|
`Proxy route: ${input.proxyRoute ?? 'unknown'}`,
|
|
`Splash status: ${input.splashStatus ?? 'unknown'}`,
|
|
`Updater status: ${input.updaterStatus ?? 'unknown'}`,
|
|
`Pending module: ${input.pendingModule ?? 'none'}`,
|
|
`Downloaded: ${formatBytes(input.receivedBytes)} of ${formatBytes(input.totalBytes)}`,
|
|
`Speed: ${input.bytesPerSecond == null ? 'unknown' : `${Math.round(input.bytesPerSecond)} bytes/s`}`,
|
|
`Last updater error: ${input.lastError ?? 'none'}`,
|
|
`Last updater error at: ${formatTime(input.lastErrorAt)}`,
|
|
'Committed modules:',
|
|
...(committed.length === 0 ? [' none'] : committed),
|
|
];
|
|
return redactDiagnosticText(lines.join('\n'));
|
|
}
|