| 118 | }; |
| 119 | |
| 120 | const parseStackTrace = (trace: string): ParsedStackTrace => { |
| 121 | const lines = trace.split("\n").filter((line) => line.trim()); |
| 122 | |
| 123 | if (lines.length === 0) { |
| 124 | return { |
| 125 | errorMessage: trace, |
| 126 | errorType: null, |
| 127 | frames: [], |
| 128 | raw: trace, |
| 129 | }; |
| 130 | } |
| 131 | |
| 132 | const firstLine = lines[0].trim(); |
| 133 | let errorType: string | null = null; |
| 134 | let errorMessage = firstLine; |
| 135 | |
| 136 | // Try to extract error type from "ErrorType: message" format |
| 137 | const errorMatch = firstLine.match(ERROR_TYPE_REGEX); |
| 138 | if (errorMatch) { |
| 139 | const [, type, msg] = errorMatch; |
| 140 | errorType = type; |
| 141 | errorMessage = msg || ""; |
| 142 | } |
| 143 | |
| 144 | // Parse stack frames (lines starting with "at") |
| 145 | const frames = lines |
| 146 | .slice(1) |
| 147 | .filter((line) => line.trim().startsWith("at ")) |
| 148 | .map(parseStackFrame); |
| 149 | |
| 150 | return { |
| 151 | errorMessage, |
| 152 | errorType, |
| 153 | frames, |
| 154 | raw: trace, |
| 155 | }; |
| 156 | }; |
| 157 | |
| 158 | export type StackTraceProps = ComponentProps<"div"> & { |
| 159 | trace: string; |