feat(diagnostics-client): implement Phase 2.1 TypeScript SDK
New package @bytelyst/diagnostics-client with: - DiagnosticsClient: singleton with polling for active sessions - BreadcrumbTrail: ring buffer (max 100) for timeline - NetworkInterceptor: fetch wrapper for HTTP capture - DeviceState: memory, storage, network collection - 21 Vitest tests (all passing)
This commit is contained in:
parent
18dd263797
commit
8acb8db7d7
@ -7,24 +7,19 @@
|
||||
import type { DeviceState } from './types.js';
|
||||
|
||||
// DOM type declarations for ESLint
|
||||
declare const navigator: Navigator & {
|
||||
connection?: NetworkInformation;
|
||||
getBattery?: () => Promise<BatteryManager>;
|
||||
type Navigator = {
|
||||
onLine: boolean;
|
||||
connection?: { effectiveType?: string };
|
||||
getBattery?: () => Promise<{ charging: boolean; level: number }>;
|
||||
storage?: { estimate(): Promise<{ usage?: number }> };
|
||||
};
|
||||
declare const performance: Performance & { memory?: { usedJSHeapSize: number } };
|
||||
declare const window: Window & {
|
||||
addEventListener: (type: string, listener: EventListener) => void;
|
||||
removeEventListener: (type: string, listener: EventListener) => void;
|
||||
};
|
||||
type EventListener = (event: { isTrusted: boolean }) => void;
|
||||
interface NetworkInformation {
|
||||
effectiveType?: string;
|
||||
}
|
||||
interface BatteryManager {
|
||||
charging: boolean;
|
||||
level: number;
|
||||
declare const navigator: Navigator;
|
||||
declare const performance: { memory?: { usedJSHeapSize: number } };
|
||||
interface Window {
|
||||
addEventListener: (type: string, listener: () => void) => void;
|
||||
removeEventListener: (type: string, listener: () => void) => void;
|
||||
}
|
||||
declare const window: Window;
|
||||
|
||||
/**
|
||||
* Collect current device state
|
||||
@ -36,34 +31,39 @@ export function collectDeviceState(): DeviceState {
|
||||
};
|
||||
|
||||
// Network type (experimental API)
|
||||
const connection = (navigator as Navigator & { connection?: NetworkInformation }).connection;
|
||||
const connection = (navigator as { connection?: { effectiveType?: string } }).connection;
|
||||
if (connection) {
|
||||
state.networkType = connection.effectiveType ?? 'unknown';
|
||||
}
|
||||
|
||||
// Battery API (experimental, not widely supported)
|
||||
// Note: Battery API is deprecated but still useful for diagnostics
|
||||
const battery = (navigator as Navigator & { getBattery?: () => Promise<BatteryManager> }).getBattery;
|
||||
const battery = (
|
||||
navigator as { getBattery?: () => Promise<{ charging: boolean; level: number }> }
|
||||
).getBattery;
|
||||
if (battery) {
|
||||
// We'll return a promise, but sync API can't wait
|
||||
// Store last known value if available
|
||||
}
|
||||
|
||||
// Memory (Chrome-only experimental)
|
||||
const memory = (performance as Performance & { memory?: { usedJSHeapSize: number } }).memory;
|
||||
const memory = (performance as { memory?: { usedJSHeapSize: number } }).memory;
|
||||
if (memory) {
|
||||
state.memoryMB = Math.round(memory.usedJSHeapSize / 1024 / 1024);
|
||||
}
|
||||
|
||||
// Storage (async, but we'll fire-and-forget)
|
||||
if (navigator.storage && navigator.storage.estimate) {
|
||||
navigator.storage.estimate().then(estimate => {
|
||||
if (estimate.usage !== undefined) {
|
||||
state.storageMB = Math.round(estimate.usage / 1024 / 1024);
|
||||
}
|
||||
}).catch(() => {
|
||||
// Ignore errors
|
||||
});
|
||||
navigator.storage
|
||||
.estimate()
|
||||
.then(estimate => {
|
||||
if (estimate.usage !== undefined) {
|
||||
state.storageMB = Math.round(estimate.usage / 1024 / 1024);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Ignore errors
|
||||
});
|
||||
}
|
||||
|
||||
return state;
|
||||
@ -72,9 +72,7 @@ export function collectDeviceState(): DeviceState {
|
||||
/**
|
||||
* Subscribe to online/offline events
|
||||
*/
|
||||
export function subscribeToConnectivity(
|
||||
callback: (isOnline: boolean) => void
|
||||
): () => void {
|
||||
export function subscribeToConnectivity(callback: (isOnline: boolean) => void): () => void {
|
||||
const handleOnline = () => callback(true);
|
||||
const handleOffline = () => callback(false);
|
||||
|
||||
@ -86,25 +84,3 @@ export function subscribeToConnectivity(
|
||||
window.removeEventListener('offline', handleOffline);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Information interface (experimental)
|
||||
*/
|
||||
interface NetworkInformation {
|
||||
effectiveType?: string;
|
||||
downlink?: number;
|
||||
rtt?: number;
|
||||
saveData?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Battery Manager interface (experimental)
|
||||
*/
|
||||
interface BatteryManager {
|
||||
charging: boolean;
|
||||
level: number;
|
||||
chargingTime: number;
|
||||
dischargingTime: number;
|
||||
addEventListener: (type: string, listener: EventListener) => void;
|
||||
removeEventListener: (type: string, listener: EventListener) => void;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user