Files
Starlight_Lancher/apps/app-frontend/src/composables/useCrashAnalysis.ts
T

130 lines
2.7 KiB
TypeScript

import { type Ref, ref } from 'vue'
import { analyze_crash } from '@/helpers/logs'
export interface CrashAnalysisEvidence {
filename: string
line: number
text: string
}
export interface CrashAnalysisFinding {
id: string
confidence: 'high' | 'medium'
evidence: CrashAnalysisEvidence[]
}
export interface CrashAnalysisMod {
file_name: string
id?: string
name?: string
matched_class?: string
}
export interface CrashModChange {
kind: 'added' | 'removed' | 'modified'
filename: string
previous_size?: number
current_size?: number
current_sha256?: string
project_id?: string
project_title?: string
icon_url?: string
version_id?: string
version_number?: string
}
export interface CrashModChangeCounts {
added: number
removed: number
modified: number
}
export interface WindowsCrashEvent {
event_id: number
provider: string
time_created: string
message: string
}
export interface CrashAnalysisResult {
instance_id: string
ruleset: string
crashed: boolean
sources: Array<{
filename: string
source_type: string
modified_at: number
line_count: number
content: string
}>
findings: CrashAnalysisFinding[]
mods: CrashAnalysisMod[]
combined_log: string
mod_changes: CrashModChange[]
mod_change_counts: CrashModChangeCounts
windows_events: WindowsCrashEvent[]
}
interface CrashAnalysisState {
analysis: Ref<CrashAnalysisResult | null>
loading: Ref<boolean>
error: Ref<unknown>
pending?: Promise<CrashAnalysisResult | null>
}
const states = new Map<string, CrashAnalysisState>()
function getState(instanceId: string): CrashAnalysisState {
let state = states.get(instanceId)
if (!state) {
state = {
analysis: ref(null),
loading: ref(false),
error: ref(null),
}
states.set(instanceId, state)
}
return state
}
export async function refreshCrashAnalysis(
instanceId: string,
): Promise<CrashAnalysisResult | null> {
const state = getState(instanceId)
if (state.pending) return state.pending
state.loading.value = true
state.error.value = null
state.pending = analyze_crash(instanceId)
.then((analysis: CrashAnalysisResult) => {
state.analysis.value = analysis
return analysis
})
.catch((error) => {
state.error.value = error
throw error
})
.finally(() => {
state.loading.value = false
state.pending = undefined
})
return state.pending
}
export function clearCrashAnalysis(instanceId: string): void {
const state = getState(instanceId)
state.analysis.value = null
state.error.value = null
}
export function useCrashAnalysis(instanceId: string) {
const state = getState(instanceId)
return {
analysis: state.analysis,
loading: state.loading,
error: state.error,
refresh: () => refreshCrashAnalysis(instanceId),
clear: () => clearCrashAnalysis(instanceId),
}
}