Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 7x 7x 7x 3x 3x 4x 4x 7x 2x 2x 2x 4x 4x 4x 7x 7x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 8x 9x 1x 1x 1x 7x 7x 7x 7x 7x 7x 7x 9x 9x 9x 9x 9x 9x 7x 7x 7x 6x 5x 7x 7x 2x 2x 7x 7x 7x 7x 7x 7x 7x 7x 7x 9x 9x 9x 1x 1x 1x 1x 9x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x | /**
* @file systemInfo.ts
* @description
* System information retrieval from backend health endpoint.
* Auto-detects database type and other system characteristics.
*
* @enterprise
* - Single source of truth: /api/health endpoint
* - Auto-detection logic: "Oracle" in response → "Oracle ADB", else "Local H2"
* - Caching to avoid excessive requests
* - Fallback values for reliability
*
* @usage
* import { getSystemInfo } from '../utils/systemInfo'
* const info = await getSystemInfo()
*/
export interface SystemInfoResponse {
status: string;
components?: {
db?: {
status: string;
details?: {
database?: string;
[key: string]: unknown;
};
};
[key: string]: unknown;
};
[key: string]: unknown;
}
/**
* Detect database type from health endpoint response.
* Smart detection: if "Oracle" appears in any string, it's Oracle ADB.
* Otherwise, defaults to "Local H2" (development database).
* @param healthResponse - Response from /api/health endpoint
* @returns Database type string
*/
const detectDatabase = (healthResponse: unknown): string => {
try {
const response = healthResponse as SystemInfoResponse;
// Check if response contains Oracle database indicators
const responseString = JSON.stringify(response).toUpperCase();
if (responseString.includes('ORACLE')) {
return 'Oracle ADB';
}
// Check database details if available
if (response.components?.db?.details?.database) {
const db = response.components.db.details.database.toUpperCase();
if (db.includes('ORACLE')) {
return 'Oracle ADB';
}
}
// Default to Local H2 for development
return 'Local H2';
} catch {
// Fallback if parsing fails
return 'Local H2';
}
};
/**
* Retrieve system information from backend health endpoint.
* Includes app version, database type, environment, etc.
* @returns System info object with database, version, and environment details
* @throws May log errors but always returns fallback values
*
* @example
* const systemInfo = await getSystemInfo()
* console.log(systemInfo.database) // → 'Oracle ADB' or 'Local H2'
* console.log(systemInfo.version) // → 'v2.0.0' or 'dev'
* console.log(systemInfo.environment) // → 'production' or 'development'
*/
export const getSystemInfo = async () => {
// Fallback values for reliability
const fallback = {
database: 'Local H2',
version: 'dev',
environment: 'development',
apiVersion: 'unknown',
buildDate: 'unknown',
uptime: '0h',
status: 'unknown' as const,
};
try {
const response = await fetch('/api/health', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
// No timeout needed - browser default is used
});
if (!response.ok) {
console.warn(`Health endpoint returned status ${response.status}`);
return fallback;
}
const data = (await response.json()) as SystemInfoResponse;
// Detect database from response
const database = detectDatabase(data);
// Determine environment based on database type
const environment = database === 'Oracle ADB' ? 'production' : 'development';
// Extract version from response if available
// Backends may include version in different locations
let version = 'dev';
if (typeof data === 'object' && data !== null) {
// Try common version locations
const versionFromResponse =
(data as unknown as Record<string, unknown>).version ||
(data as unknown as Record<string, unknown>)['app-version'] ||
(data as unknown as Record<string, unknown>)['build-version'];
if (typeof versionFromResponse === 'string') {
version = versionFromResponse.startsWith('v') ? versionFromResponse : `v${versionFromResponse}`;
}
}
return {
database,
version,
environment,
apiVersion: 'v1',
buildDate: new Date().toISOString().split('T')[0],
uptime: '0h', // Could be extended with actual uptime from backend if provided
status: data.status || 'UP',
};
} catch (error) {
// Log the error for debugging but don't throw - return fallback
console.error('Failed to fetch system info from health endpoint:', error);
return fallback;
}
};
/**
* Check if system is in production based on database type.
* Useful for conditionally showing features/warnings.
* @returns boolean indicating if production environment
* @example
* if (await isProduction()) {
* // Show production warning
* }
*/
export const isProduction = async (): Promise<boolean> => {
const info = await getSystemInfo();
return info.environment === 'production';
};
/**
* Format uptime string for display.
* @param uptimeSeconds - Uptime in seconds
* @returns Formatted uptime string
* @example
* formatUptime(3661) // → '1h 1m'
* formatUptime(60) // → '1m'
* formatUptime(3661) // → '1h 1m 1s'
*/
export const formatUptime = (uptimeSeconds: number): string => {
const hours = Math.floor(uptimeSeconds / 3600);
const minutes = Math.floor((uptimeSeconds % 3600) / 60);
const seconds = uptimeSeconds % 60;
const parts: string[] = [];
if (hours > 0) parts.push(`${hours}h`);
if (minutes > 0) parts.push(`${minutes}m`);
if (seconds > 0 || parts.length === 0) parts.push(`${seconds}s`);
return parts.join(' ');
};
|