auto-error-explainer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ import { f as ExplainerMode, e as ExplainerLanguage, a as ExplainResult } from './types-BZ2cTa_U.js';
2
+
3
+ interface BrowserInitOptions {
4
+ mode?: ExplainerMode;
5
+ language?: ExplainerLanguage;
6
+ overlay?: boolean;
7
+ redact?: boolean;
8
+ onExplained?: (result: ExplainResult) => void;
9
+ }
10
+ interface BrowserController {
11
+ stop: () => void;
12
+ }
13
+ declare function initAutoErrorExplainer(options?: BrowserInitOptions): BrowserController;
14
+
15
+ export { type BrowserController, type BrowserInitOptions, initAutoErrorExplainer };
@@ -0,0 +1,483 @@
1
+ // src/core/stack.ts
2
+ function simplifyStack(stack) {
3
+ const lines = stack.split(/\r?\n/).map((l) => l.trimEnd());
4
+ const headline = lines[0]?.trim();
5
+ const frames = [];
6
+ for (const rawLine of lines.slice(1)) {
7
+ const line = rawLine.trim();
8
+ if (!line) continue;
9
+ const v8 = parseV8Frame(line);
10
+ if (v8) {
11
+ frames.push(v8);
12
+ continue;
13
+ }
14
+ const ff = parseFirefoxFrame(line);
15
+ if (ff) {
16
+ frames.push(ff);
17
+ continue;
18
+ }
19
+ frames.push({ raw: line });
20
+ }
21
+ return {
22
+ headline,
23
+ frames,
24
+ raw: stack
25
+ };
26
+ }
27
+ function parseV8Frame(line) {
28
+ const trimmed = line.startsWith("at ") ? line.slice(3).trim() : line;
29
+ const m1 = trimmed.match(/^(.*?) \((.*?):(\d+):(\d+)\)$/);
30
+ if (m1) {
31
+ return {
32
+ functionName: m1[1] || void 0,
33
+ file: m1[2],
34
+ line: Number(m1[3]),
35
+ column: Number(m1[4]),
36
+ raw: line
37
+ };
38
+ }
39
+ const m2 = trimmed.match(/^(.*?):(\d+):(\d+)$/);
40
+ if (m2) {
41
+ return {
42
+ file: m2[1],
43
+ line: Number(m2[2]),
44
+ column: Number(m2[3]),
45
+ raw: line
46
+ };
47
+ }
48
+ return void 0;
49
+ }
50
+ function parseFirefoxFrame(line) {
51
+ const m = line.match(/^(.*?)@(.*?):(\d+):(\d+)$/);
52
+ if (!m) return void 0;
53
+ return {
54
+ functionName: m[1] || void 0,
55
+ file: m[2],
56
+ line: Number(m[3]),
57
+ column: Number(m[4]),
58
+ raw: line
59
+ };
60
+ }
61
+
62
+ // src/core/similarity.ts
63
+ function similarity(a, b) {
64
+ if (!a && !b) return 1;
65
+ if (!a || !b) return 0;
66
+ if (a === b) return 1;
67
+ const dist = levenshtein(a, b);
68
+ const maxLen = Math.max(a.length, b.length);
69
+ return maxLen === 0 ? 1 : Math.max(0, 1 - dist / maxLen);
70
+ }
71
+ function levenshtein(a, b) {
72
+ const m = a.length;
73
+ const n = b.length;
74
+ const dp = new Array(n + 1);
75
+ for (let j = 0; j <= n; j++) dp[j] = j;
76
+ for (let i = 1; i <= m; i++) {
77
+ let prev = dp[0];
78
+ dp[0] = i;
79
+ for (let j = 1; j <= n; j++) {
80
+ const tmp = dp[j];
81
+ const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;
82
+ dp[j] = Math.min(dp[j] + 1, dp[j - 1] + 1, prev + cost);
83
+ prev = tmp;
84
+ }
85
+ }
86
+ return dp[n];
87
+ }
88
+
89
+ // src/core/matcher.ts
90
+ function matchPattern(input, patterns2) {
91
+ const message = (input.message ?? "").toLowerCase();
92
+ const name = input.name?.toLowerCase();
93
+ let best;
94
+ for (const p of patterns2) {
95
+ if (p.match.name && name && p.match.name.toLowerCase() !== name) continue;
96
+ let score = 0;
97
+ if (p.match.messageIncludes?.length) {
98
+ const hitCount = p.match.messageIncludes.filter((s) => message.includes(s.toLowerCase())).length;
99
+ score = Math.max(score, hitCount / p.match.messageIncludes.length);
100
+ }
101
+ if (p.match.messageRegex) {
102
+ try {
103
+ const re = new RegExp(p.match.messageRegex, "i");
104
+ if (re.test(input.message)) score = Math.max(score, 0.9);
105
+ } catch {
106
+ }
107
+ }
108
+ if (score < 0.6 && p.match.messageIncludes?.length) {
109
+ const target = p.match.messageIncludes.join(" ").toLowerCase();
110
+ score = Math.max(score, similarity(message, target));
111
+ }
112
+ if (!best || score > best.score) best = { pattern: p, score };
113
+ }
114
+ if (!best) return void 0;
115
+ if (best.score < 0.55) return void 0;
116
+ return best;
117
+ }
118
+
119
+ // src/core/patterns.ts
120
+ var patterns = [
121
+ {
122
+ id: "js-cannot-read-properties-of-undefined",
123
+ match: {
124
+ messageIncludes: ["Cannot read properties of undefined", "cannot read property"]
125
+ },
126
+ explanation: {
127
+ en: {
128
+ title: "Tried to access a property on undefined",
129
+ whatHappened: "Your code attempted to read a property from a value that was undefined.",
130
+ whyHappened: "A variable you expected to be an object was actually undefined at runtime (often due to async data, missing props, or initial state).",
131
+ fixes: [
132
+ {
133
+ title: "Add optional chaining",
134
+ description: "Safely access nested properties when values may be undefined.",
135
+ snippet: "const name = user?.profile?.name;"
136
+ },
137
+ {
138
+ title: "Provide default values",
139
+ description: "Initialize state/props with safe defaults before rendering.",
140
+ snippet: "const [user, setUser] = useState<User | null>(null);\n\nif (!user) return null;"
141
+ },
142
+ {
143
+ title: "Check API data before use",
144
+ description: "Validate response shape and handle loading/error states."
145
+ }
146
+ ]
147
+ },
148
+ bn: {
149
+ title: "undefined \u09A5\u09C7\u0995\u09C7 property \u09AA\u09DC\u09A4\u09C7 \u099A\u09C7\u09B7\u09CD\u099F\u09BE \u0995\u09B0\u09BE \u09B9\u09DF\u09C7\u099B\u09C7",
150
+ whatHappened: "\u0986\u09AA\u09A8\u09BE\u09B0 \u0995\u09CB\u09A1 \u098F\u0995\u099F\u09BF undefined value \u09A5\u09C7\u0995\u09C7 property \u09AA\u09DC\u09A4\u09C7 \u099A\u09C7\u09B7\u09CD\u099F\u09BE \u0995\u09B0\u09C7\u099B\u09C7\u0964",
151
+ whyHappened: "\u09AF\u09C7 variable-\u099F\u09BE object \u09B9\u0993\u09DF\u09BE\u09B0 \u0995\u09A5\u09BE \u099B\u09BF\u09B2, runtime-\u098F \u09B8\u09C7\u099F\u09BE undefined \u099B\u09BF\u09B2 (async data, missing props, \u09AC\u09BE initial state \u09A0\u09BF\u0995 \u09A8\u09BE \u09A5\u09BE\u0995\u09BE\u09B0 \u0995\u09BE\u09B0\u09A3\u09C7 \u09B9\u09A4\u09C7 \u09AA\u09BE\u09B0\u09C7)\u0964",
152
+ fixes: [
153
+ {
154
+ title: "Optional chaining \u09AC\u09CD\u09AF\u09AC\u09B9\u09BE\u09B0 \u0995\u09B0\u09C1\u09A8",
155
+ description: "value undefined \u09B9\u09A4\u09C7 \u09AA\u09BE\u09B0\u09C7 \u098F\u09AE\u09A8 \u0995\u09CD\u09B7\u09C7\u09A4\u09CD\u09B0\u09C7 safe access \u09A6\u09BF\u09A8\u0964",
156
+ snippet: "const name = user?.profile?.name;"
157
+ },
158
+ {
159
+ title: "Default value \u09A6\u09BF\u09A8",
160
+ description: "render \u0995\u09B0\u09BE\u09B0 \u0986\u0997\u09C7 state/props safe default \u09A6\u09BF\u09DF\u09C7 initialize \u0995\u09B0\u09C1\u09A8\u0964",
161
+ snippet: "const [user, setUser] = useState<User | null>(null);\n\nif (!user) return null;"
162
+ },
163
+ {
164
+ title: "API data \u09AF\u09BE\u099A\u09BE\u0987 \u0995\u09B0\u09C1\u09A8",
165
+ description: "response shape validate \u0995\u09B0\u09C1\u09A8 \u098F\u09AC\u0982 loading/error state handle \u0995\u09B0\u09C1\u09A8\u0964"
166
+ }
167
+ ]
168
+ }
169
+ }
170
+ },
171
+ {
172
+ id: "react-invalid-hook-call",
173
+ match: {
174
+ messageIncludes: ["Invalid hook call"]
175
+ },
176
+ explanation: {
177
+ en: {
178
+ title: "Invalid React Hook usage",
179
+ whatHappened: "React detected a Hook being called in an unsupported place.",
180
+ whyHappened: "Hooks must be called at the top level of React function components or custom hooks. This can also happen if you have multiple React versions.",
181
+ fixes: [
182
+ {
183
+ title: "Move hooks to top level",
184
+ description: "Do not call hooks inside conditions, loops, or nested functions.",
185
+ snippet: "function Component() {\n const [state, setState] = useState(0);\n // ...\n}"
186
+ },
187
+ {
188
+ title: "Check duplicate React versions",
189
+ description: "Ensure your app and packages resolve to a single React installation."
190
+ }
191
+ ]
192
+ },
193
+ bn: {
194
+ title: "React Hook \u09AD\u09C1\u09B2 \u099C\u09BE\u09DF\u0997\u09BE\u09DF call \u0995\u09B0\u09BE \u09B9\u09DF\u09C7\u099B\u09C7",
195
+ whatHappened: "React \u09A6\u09C7\u0996\u09C7\u099B\u09C7 Hook \u098F\u09AE\u09A8 \u099C\u09BE\u09DF\u0997\u09BE\u09DF call \u0995\u09B0\u09BE \u09B9\u09DF\u09C7\u099B\u09C7 \u09AF\u09C7\u0996\u09BE\u09A8\u09C7 \u0995\u09B0\u09BE \u09AF\u09BE\u09DF \u09A8\u09BE\u0964",
196
+ whyHappened: "Hooks \u09B8\u09AC\u09B8\u09AE\u09DF React function component \u09AC\u09BE custom hook-\u098F\u09B0 top level-\u098F call \u0995\u09B0\u09A4\u09C7 \u09B9\u09DF\u0964 \u098F\u0995\u09BE\u09A7\u09BF\u0995 React version \u09A5\u09BE\u0995\u09B2\u09C7\u0993 \u098F\u09AE\u09A8 \u09B9\u09A4\u09C7 \u09AA\u09BE\u09B0\u09C7\u0964",
197
+ fixes: [
198
+ {
199
+ title: "Hook top level-\u098F \u09B0\u09BE\u0996\u09C1\u09A8",
200
+ description: "condition/loop/nested function-\u098F\u09B0 \u09AD\u09BF\u09A4\u09B0\u09C7 Hook call \u0995\u09B0\u09AC\u09C7\u09A8 \u09A8\u09BE\u0964",
201
+ snippet: "function Component() {\n const [state, setState] = useState(0);\n // ...\n}"
202
+ },
203
+ {
204
+ title: "React version duplication \u099A\u09C7\u0995 \u0995\u09B0\u09C1\u09A8",
205
+ description: "\u098F\u0995\u099F\u09BE\u0987 React resolve \u09B9\u099A\u09CD\u099B\u09C7 \u0995\u09BF\u09A8\u09BE \u09A8\u09BF\u09B6\u09CD\u099A\u09BF\u09A4 \u0995\u09B0\u09C1\u09A8\u0964"
206
+ }
207
+ ]
208
+ }
209
+ }
210
+ },
211
+ {
212
+ id: "nextjs-hydration-failed",
213
+ match: {
214
+ messageIncludes: ["Hydration failed", "did not match"],
215
+ messageRegex: "Hydration failed|did not match"
216
+ },
217
+ explanation: {
218
+ en: {
219
+ title: "Hydration mismatch (Next.js/React SSR)",
220
+ whatHappened: "The HTML rendered on the server did not match what React rendered on the client.",
221
+ whyHappened: "Client-only values (Date, Math.random, window, locale formatting) or conditional rendering based on browser state can cause SSR vs CSR differences.",
222
+ fixes: [
223
+ {
224
+ title: "Move client-only logic into useEffect",
225
+ description: "Compute values after mount so server and client match initially.",
226
+ snippet: "const [mounted, setMounted] = useState(false);\nuseEffect(() => setMounted(true), []);\nif (!mounted) return null;"
227
+ },
228
+ {
229
+ title: "Avoid random/Date in initial render",
230
+ description: "Generate such values on the client after mount, or pass them from the server."
231
+ }
232
+ ]
233
+ },
234
+ bn: {
235
+ title: "Hydration mismatch (Next.js/React SSR)",
236
+ whatHappened: "server \u09A5\u09C7\u0995\u09C7 \u09AF\u09C7 HTML \u098F\u09B8\u09C7\u099B\u09C7, client-\u098F React \u09AF\u09C7 HTML \u09AC\u09BE\u09A8\u09BF\u09DF\u09C7\u099B\u09C7 \u09B8\u09C7\u099F\u09BE \u09AE\u09BF\u09B2\u09C7\u09A8\u09BF\u0964",
237
+ whyHappened: "Date/Math.random/window/locale formatting \u09AC\u09BE browser state based conditional rendering SSR \u0986\u09B0 CSR-\u098F \u0986\u09B2\u09BE\u09A6\u09BE output \u09A6\u09BF\u09A4\u09C7 \u09AA\u09BE\u09B0\u09C7\u0964",
238
+ fixes: [
239
+ {
240
+ title: "client-only logic useEffect-\u098F \u09A8\u09BF\u09A8",
241
+ description: "mount \u09B9\u0993\u09DF\u09BE\u09B0 \u09AA\u09B0\u09C7 value compute \u0995\u09B0\u09C1\u09A8 \u09AF\u09BE\u09A4\u09C7 \u09B6\u09C1\u09B0\u09C1\u09A4\u09C7 server/client \u098F\u0995 \u09A5\u09BE\u0995\u09C7\u0964",
242
+ snippet: "const [mounted, setMounted] = useState(false);\nuseEffect(() => setMounted(true), []);\nif (!mounted) return null;"
243
+ },
244
+ {
245
+ title: "initial render-\u098F random/Date \u098F\u09DC\u09BF\u09DF\u09C7 \u099A\u09B2\u09C1\u09A8",
246
+ description: "mount-\u098F\u09B0 \u09AA\u09B0\u09C7 generate \u0995\u09B0\u09C1\u09A8, \u09AC\u09BE server \u09A5\u09C7\u0995\u09C7 pass \u0995\u09B0\u09C1\u09A8\u0964"
247
+ }
248
+ ]
249
+ }
250
+ }
251
+ }
252
+ ];
253
+
254
+ // src/core/explain.ts
255
+ function explainError(input, options = {}) {
256
+ const mode = options.mode ?? "beginner";
257
+ const language = options.language ?? "en";
258
+ const simplifiedStack = input.stack ? simplifyStack(input.stack) : void 0;
259
+ const matched = matchPattern({ name: input.name, message: input.message }, patterns);
260
+ const best = matched?.pattern;
261
+ if (best) {
262
+ const localized = best.explanation[language];
263
+ const confidence = matched?.score ?? 0.6;
264
+ return {
265
+ input: {
266
+ name: input.name,
267
+ message: input.message,
268
+ stack: input.stack,
269
+ cause: input.cause
270
+ },
271
+ title: localized.title,
272
+ whatHappened: localized.whatHappened,
273
+ whyHappened: localized.whyHappened,
274
+ suggestedFixes: localized.fixes,
275
+ simplifiedStack,
276
+ confidence,
277
+ matchedPatternId: best.id
278
+ };
279
+ }
280
+ const fallback = buildFallback(input.message, language, mode);
281
+ return {
282
+ input: {
283
+ name: input.name,
284
+ message: input.message,
285
+ stack: input.stack,
286
+ cause: input.cause
287
+ },
288
+ ...fallback,
289
+ simplifiedStack,
290
+ confidence: 0.2
291
+ };
292
+ }
293
+ function buildFallback(message, language, mode) {
294
+ if (language === "bn") {
295
+ return {
296
+ title: "\u0985\u09AA\u09B0\u09BF\u099A\u09BF\u09A4 Error",
297
+ whatHappened: `\u0985\u09CD\u09AF\u09BE\u09AA\u099F\u09BF \u098F\u0995\u099F\u09BF error \u09A6\u09BF\u09DF\u09C7\u099B\u09C7: ${message}`,
298
+ whyHappened: mode === "pro" ? "\u098F\u0987 error-\u098F\u09B0 \u09A8\u09BF\u09B0\u09CD\u09A6\u09BF\u09B7\u09CD\u099F pattern \u09A1\u09BE\u099F\u09BE\u09AC\u09C7\u09B8\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF\u0964 stack trace/\u0995\u09CB\u09A1 context \u09A6\u09C7\u0996\u09C7 root cause \u09AC\u09C7\u09B0 \u0995\u09B0\u09A4\u09C7 \u09B9\u09AC\u09C7\u0964" : "\u098F\u0987 error \u0995\u09C7\u09A8 \u09B9\u09DF\u09C7\u099B\u09C7 \u09B8\u09C7\u099F\u09BE \u09A8\u09BF\u09B6\u09CD\u099A\u09BF\u09A4 \u09A8\u09BE\u2014\u0995\u09CB\u09A1/\u09A1\u09BE\u099F\u09BE \u09AF\u09BE\u099A\u09BE\u0987 \u0995\u09B0\u09A4\u09C7 \u09B9\u09AC\u09C7\u0964",
299
+ suggestedFixes: [
300
+ {
301
+ title: "Stack trace \u09A6\u09C7\u0996\u09C1\u09A8",
302
+ description: "\u09AF\u09C7\u0996\u09BE\u09A8\u09C7 error \u09B9\u09DF\u09C7\u099B\u09C7 \u09B8\u09C7\u0987 file + line identify \u0995\u09B0\u09C1\u09A8\u0964"
303
+ },
304
+ {
305
+ title: "Null/undefined guard \u09A6\u09BF\u09A8",
306
+ description: "object/property \u09AC\u09CD\u09AF\u09AC\u09B9\u09BE\u09B0 \u0995\u09B0\u09BE\u09B0 \u0986\u0997\u09C7 value \u0986\u099B\u09C7 \u0995\u09BF\u09A8\u09BE \u099A\u09C7\u0995 \u0995\u09B0\u09C1\u09A8\u0964",
307
+ snippet: "if (value == null) return;\n// or\nconst safe = obj?.prop;"
308
+ }
309
+ ]
310
+ };
311
+ }
312
+ return {
313
+ title: "Unknown Error",
314
+ whatHappened: `Your app threw an error: ${message}`,
315
+ whyHappened: mode === "pro" ? "No known pattern matched this error. Use the stack trace and runtime context to identify the root cause." : "This error didn't match a known pattern. Check your data and the line where it happened.",
316
+ suggestedFixes: [
317
+ {
318
+ title: "Inspect the stack trace",
319
+ description: "Identify the exact file and line where the error originated."
320
+ },
321
+ {
322
+ title: "Add null/undefined guards",
323
+ description: "Check values before accessing properties or calling functions.",
324
+ snippet: "if (value == null) return;\n// or\nconst safe = obj?.prop;"
325
+ }
326
+ ]
327
+ };
328
+ }
329
+
330
+ // src/ui/overlay.ts
331
+ function createOverlay(opts) {
332
+ const root = document.createElement("div");
333
+ root.id = "auto-error-explainer-overlay";
334
+ root.style.position = "fixed";
335
+ root.style.left = "0";
336
+ root.style.right = "0";
337
+ root.style.top = "0";
338
+ root.style.zIndex = "2147483647";
339
+ root.style.fontFamily = "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial";
340
+ root.style.pointerEvents = "none";
341
+ const panel = document.createElement("div");
342
+ panel.style.margin = "12px";
343
+ panel.style.padding = "12px 14px";
344
+ panel.style.background = "rgba(17, 24, 39, 0.96)";
345
+ panel.style.color = "#fff";
346
+ panel.style.border = "1px solid rgba(255,255,255,0.12)";
347
+ panel.style.borderRadius = "10px";
348
+ panel.style.boxShadow = "0 10px 30px rgba(0,0,0,0.45)";
349
+ panel.style.maxHeight = "50vh";
350
+ panel.style.overflow = "auto";
351
+ panel.style.pointerEvents = "auto";
352
+ const header = document.createElement("div");
353
+ header.style.display = "flex";
354
+ header.style.alignItems = "center";
355
+ header.style.justifyContent = "space-between";
356
+ header.style.gap = "10px";
357
+ const title = document.createElement("div");
358
+ title.style.fontWeight = "700";
359
+ title.style.fontSize = "14px";
360
+ const closeBtn = document.createElement("button");
361
+ closeBtn.type = "button";
362
+ closeBtn.textContent = opts.language === "bn" ? "\u09AC\u09A8\u09CD\u09A7" : "Close";
363
+ closeBtn.style.fontSize = "12px";
364
+ closeBtn.style.padding = "6px 10px";
365
+ closeBtn.style.borderRadius = "8px";
366
+ closeBtn.style.border = "1px solid rgba(255,255,255,0.18)";
367
+ closeBtn.style.background = "rgba(255,255,255,0.08)";
368
+ closeBtn.style.color = "#fff";
369
+ closeBtn.style.cursor = "pointer";
370
+ const body = document.createElement("div");
371
+ body.style.marginTop = "10px";
372
+ body.style.fontSize = "12px";
373
+ body.style.lineHeight = "1.45";
374
+ header.appendChild(title);
375
+ header.appendChild(closeBtn);
376
+ panel.appendChild(header);
377
+ panel.appendChild(body);
378
+ root.appendChild(panel);
379
+ let mounted = false;
380
+ const mount = () => {
381
+ if (mounted) return;
382
+ document.body.appendChild(root);
383
+ mounted = true;
384
+ };
385
+ const hide = () => {
386
+ if (!mounted) return;
387
+ root.remove();
388
+ mounted = false;
389
+ };
390
+ closeBtn.addEventListener("click", hide);
391
+ return {
392
+ show: (result) => {
393
+ mount();
394
+ title.textContent = result.title;
395
+ const fixes = result.suggestedFixes.map((f) => {
396
+ const snippet = f.snippet ? `<pre style="margin:8px 0 0; padding:8px; background: rgba(0,0,0,0.35); border-radius: 8px; overflow:auto;">${escapeHtml(f.snippet)}</pre>` : "";
397
+ return `<div style="margin-top:10px; padding-top:10px; border-top: 1px solid rgba(255,255,255,0.10);">
398
+ <div style="font-weight:600;">${escapeHtml(f.title)}</div>
399
+ ${f.description ? `<div style="opacity:0.9; margin-top:4px;">${escapeHtml(f.description)}</div>` : ""}
400
+ ${snippet}
401
+ </div>`;
402
+ }).join("");
403
+ const stackTop = result.simplifiedStack?.frames?.[0];
404
+ const stackLine = stackTop?.file ? `<div style="margin-top:10px; opacity:0.9;">${escapeHtml(stackTop.file)}:${stackTop.line ?? ""}</div>` : "";
405
+ body.innerHTML = `
406
+ <div style="opacity:0.9;">${escapeHtml(result.whatHappened)}</div>
407
+ <div style="margin-top:8px; opacity:0.9;">${escapeHtml(result.whyHappened)}</div>
408
+ ${stackLine}
409
+ ${fixes}
410
+ `;
411
+ },
412
+ destroy: () => {
413
+ hide();
414
+ closeBtn.removeEventListener("click", hide);
415
+ }
416
+ };
417
+ }
418
+ function escapeHtml(s) {
419
+ return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#039;");
420
+ }
421
+
422
+ // src/browser.ts
423
+ function initAutoErrorExplainer(options = {}) {
424
+ const mode = options.mode ?? "beginner";
425
+ const language = options.language ?? "en";
426
+ const overlayEnabled = options.overlay ?? true;
427
+ const explainOpts = {
428
+ mode,
429
+ language,
430
+ source: "browser"
431
+ };
432
+ let overlay;
433
+ if (overlayEnabled && typeof window !== "undefined" && typeof document !== "undefined") {
434
+ overlay = createOverlay({ language });
435
+ }
436
+ const onResult = (result) => {
437
+ options.onExplained?.(result);
438
+ overlay?.show(result);
439
+ };
440
+ const onError = (event) => {
441
+ const message = event.message || "Unknown error";
442
+ const stack = event.error && event.error.stack || void 0;
443
+ const name = event.error && event.error.name || void 0;
444
+ const result = explainError({ message, stack, name }, explainOpts);
445
+ onResult(result);
446
+ };
447
+ const onRejection = (event) => {
448
+ const reason = event.reason;
449
+ const message = reason?.message ? String(reason.message) : String(reason ?? "Unhandled promise rejection");
450
+ const stack = reason?.stack ? String(reason.stack) : void 0;
451
+ const name = reason?.name ? String(reason.name) : void 0;
452
+ const result = explainError({ message, stack, name, cause: reason }, explainOpts);
453
+ onResult(result);
454
+ };
455
+ const originalConsoleError = console.error.bind(console);
456
+ const patchedConsoleError = (...args) => {
457
+ try {
458
+ const first = args[0];
459
+ const message = first instanceof Error ? first.message : String(first ?? "console.error");
460
+ const stack = first instanceof Error ? first.stack : void 0;
461
+ const name = first instanceof Error ? first.name : void 0;
462
+ const result = explainError({ message, stack, name, cause: args }, explainOpts);
463
+ onResult(result);
464
+ } catch {
465
+ }
466
+ originalConsoleError(...args);
467
+ };
468
+ window.addEventListener("error", onError);
469
+ window.addEventListener("unhandledrejection", onRejection);
470
+ console.error = patchedConsoleError;
471
+ return {
472
+ stop: () => {
473
+ window.removeEventListener("error", onError);
474
+ window.removeEventListener("unhandledrejection", onRejection);
475
+ console.error = originalConsoleError;
476
+ overlay?.destroy();
477
+ }
478
+ };
479
+ }
480
+
481
+ export { initAutoErrorExplainer };
482
+ //# sourceMappingURL=browser.js.map
483
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/stack.ts","../src/core/similarity.ts","../src/core/matcher.ts","../src/core/patterns.ts","../src/core/explain.ts","../src/ui/overlay.ts","../src/browser.ts"],"names":["patterns"],"mappings":"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","file":"browser.js","sourcesContent":["import type { SimplifiedStack, StackFrame } from '../types.js';\n\nexport function simplifyStack(stack: string): SimplifiedStack {\n const lines = stack.split(/\\r?\\n/).map((l) => l.trimEnd());\n const headline = lines[0]?.trim();\n\n const frames: StackFrame[] = [];\n\n for (const rawLine of lines.slice(1)) {\n const line = rawLine.trim();\n if (!line) continue;\n\n // V8 style: \"at fn (file:line:col)\" or \"at file:line:col\"\n const v8 = parseV8Frame(line);\n if (v8) {\n frames.push(v8);\n continue;\n }\n\n // Firefox style: \"fn@file:line:col\"\n const ff = parseFirefoxFrame(line);\n if (ff) {\n frames.push(ff);\n continue;\n }\n\n frames.push({ raw: line });\n }\n\n return {\n headline,\n frames,\n raw: stack\n };\n}\n\nfunction parseV8Frame(line: string): StackFrame | undefined {\n const trimmed = line.startsWith('at ') ? line.slice(3).trim() : line;\n\n // fn (file:line:col)\n const m1 = trimmed.match(/^(.*?) \\((.*?):(\\d+):(\\d+)\\)$/);\n if (m1) {\n return {\n functionName: m1[1] || undefined,\n file: m1[2],\n line: Number(m1[3]),\n column: Number(m1[4]),\n raw: line\n };\n }\n\n // file:line:col\n const m2 = trimmed.match(/^(.*?):(\\d+):(\\d+)$/);\n if (m2) {\n return {\n file: m2[1],\n line: Number(m2[2]),\n column: Number(m2[3]),\n raw: line\n };\n }\n\n return undefined;\n}\n\nfunction parseFirefoxFrame(line: string): StackFrame | undefined {\n const m = line.match(/^(.*?)@(.*?):(\\d+):(\\d+)$/);\n if (!m) return undefined;\n return {\n functionName: m[1] || undefined,\n file: m[2],\n line: Number(m[3]),\n column: Number(m[4]),\n raw: line\n };\n}\n","// Small, dependency-free similarity score (0..1)\n\nexport function similarity(a: string, b: string): number {\n if (!a && !b) return 1;\n if (!a || !b) return 0;\n if (a === b) return 1;\n\n const dist = levenshtein(a, b);\n const maxLen = Math.max(a.length, b.length);\n return maxLen === 0 ? 1 : Math.max(0, 1 - dist / maxLen);\n}\n\nfunction levenshtein(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n\n const dp: number[] = new Array(n + 1);\n for (let j = 0; j <= n; j++) dp[j] = j;\n\n for (let i = 1; i <= m; i++) {\n let prev = dp[0];\n dp[0] = i;\n for (let j = 1; j <= n; j++) {\n const tmp = dp[j];\n const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;\n dp[j] = Math.min(dp[j] + 1, dp[j - 1] + 1, prev + cost);\n prev = tmp;\n }\n }\n\n return dp[n];\n}\n","import type { Pattern } from '../types.js';\nimport { similarity } from './similarity.js';\n\nexport function matchPattern(\n input: { name?: string; message: string },\n patterns: Pattern[]\n): { pattern: Pattern; score: number } | undefined {\n const message = (input.message ?? '').toLowerCase();\n const name = input.name?.toLowerCase();\n\n let best: { pattern: Pattern; score: number } | undefined;\n\n for (const p of patterns) {\n // Hard constraints first\n if (p.match.name && name && p.match.name.toLowerCase() !== name) continue;\n\n let score = 0;\n if (p.match.messageIncludes?.length) {\n const hitCount = p.match.messageIncludes.filter((s) => message.includes(s.toLowerCase())).length;\n score = Math.max(score, hitCount / p.match.messageIncludes.length);\n }\n\n if (p.match.messageRegex) {\n try {\n const re = new RegExp(p.match.messageRegex, 'i');\n if (re.test(input.message)) score = Math.max(score, 0.9);\n } catch {\n // ignore invalid regex\n }\n }\n\n // Fuzzy fallback: compare whole message to each include token concatenation\n if (score < 0.6 && p.match.messageIncludes?.length) {\n const target = p.match.messageIncludes.join(' ').toLowerCase();\n score = Math.max(score, similarity(message, target));\n }\n\n if (!best || score > best.score) best = { pattern: p, score };\n }\n\n if (!best) return undefined;\n if (best.score < 0.55) return undefined;\n return best;\n}\n","import type { Pattern } from '../types.js';\n\nexport const patterns: Pattern[] = [\n {\n id: 'js-cannot-read-properties-of-undefined',\n match: {\n messageIncludes: ['Cannot read properties of undefined', 'cannot read property']\n },\n explanation: {\n en: {\n title: 'Tried to access a property on undefined',\n whatHappened: 'Your code attempted to read a property from a value that was undefined.',\n whyHappened: 'A variable you expected to be an object was actually undefined at runtime (often due to async data, missing props, or initial state).',\n fixes: [\n {\n title: 'Add optional chaining',\n description: 'Safely access nested properties when values may be undefined.',\n snippet: 'const name = user?.profile?.name;'\n },\n {\n title: 'Provide default values',\n description: 'Initialize state/props with safe defaults before rendering.',\n snippet: 'const [user, setUser] = useState<User | null>(null);\\n\\nif (!user) return null;'\n },\n {\n title: 'Check API data before use',\n description: 'Validate response shape and handle loading/error states.'\n }\n ]\n },\n bn: {\n title: 'undefined থেকে property পড়তে চেষ্টা করা হয়েছে',\n whatHappened: 'আপনার কোড একটি undefined value থেকে property পড়তে চেষ্টা করেছে।',\n whyHappened: 'যে variable-টা object হওয়ার কথা ছিল, runtime-এ সেটা undefined ছিল (async data, missing props, বা initial state ঠিক না থাকার কারণে হতে পারে)।',\n fixes: [\n {\n title: 'Optional chaining ব্যবহার করুন',\n description: 'value undefined হতে পারে এমন ক্ষেত্রে safe access দিন।',\n snippet: 'const name = user?.profile?.name;'\n },\n {\n title: 'Default value দিন',\n description: 'render করার আগে state/props safe default দিয়ে initialize করুন।',\n snippet: 'const [user, setUser] = useState<User | null>(null);\\n\\nif (!user) return null;'\n },\n {\n title: 'API data যাচাই করুন',\n description: 'response shape validate করুন এবং loading/error state handle করুন।'\n }\n ]\n }\n }\n },\n {\n id: 'react-invalid-hook-call',\n match: {\n messageIncludes: ['Invalid hook call']\n },\n explanation: {\n en: {\n title: 'Invalid React Hook usage',\n whatHappened: 'React detected a Hook being called in an unsupported place.',\n whyHappened: 'Hooks must be called at the top level of React function components or custom hooks. This can also happen if you have multiple React versions.',\n fixes: [\n {\n title: 'Move hooks to top level',\n description: 'Do not call hooks inside conditions, loops, or nested functions.',\n snippet: 'function Component() {\\n const [state, setState] = useState(0);\\n // ...\\n}'\n },\n {\n title: 'Check duplicate React versions',\n description: 'Ensure your app and packages resolve to a single React installation.'\n }\n ]\n },\n bn: {\n title: 'React Hook ভুল জায়গায় call করা হয়েছে',\n whatHappened: 'React দেখেছে Hook এমন জায়গায় call করা হয়েছে যেখানে করা যায় না।',\n whyHappened: 'Hooks সবসময় React function component বা custom hook-এর top level-এ call করতে হয়। একাধিক React version থাকলেও এমন হতে পারে।',\n fixes: [\n {\n title: 'Hook top level-এ রাখুন',\n description: 'condition/loop/nested function-এর ভিতরে Hook call করবেন না।',\n snippet: 'function Component() {\\n const [state, setState] = useState(0);\\n // ...\\n}'\n },\n {\n title: 'React version duplication চেক করুন',\n description: 'একটাই React resolve হচ্ছে কিনা নিশ্চিত করুন।'\n }\n ]\n }\n }\n },\n {\n id: 'nextjs-hydration-failed',\n match: {\n messageIncludes: ['Hydration failed', 'did not match'],\n messageRegex: 'Hydration failed|did not match'\n },\n explanation: {\n en: {\n title: 'Hydration mismatch (Next.js/React SSR)',\n whatHappened: 'The HTML rendered on the server did not match what React rendered on the client.',\n whyHappened: 'Client-only values (Date, Math.random, window, locale formatting) or conditional rendering based on browser state can cause SSR vs CSR differences.',\n fixes: [\n {\n title: 'Move client-only logic into useEffect',\n description: 'Compute values after mount so server and client match initially.',\n snippet: \"const [mounted, setMounted] = useState(false);\\nuseEffect(() => setMounted(true), []);\\nif (!mounted) return null;\"\n },\n {\n title: 'Avoid random/Date in initial render',\n description: 'Generate such values on the client after mount, or pass them from the server.'\n }\n ]\n },\n bn: {\n title: 'Hydration mismatch (Next.js/React SSR)',\n whatHappened: 'server থেকে যে HTML এসেছে, client-এ React যে HTML বানিয়েছে সেটা মিলেনি।',\n whyHappened: 'Date/Math.random/window/locale formatting বা browser state based conditional rendering SSR আর CSR-এ আলাদা output দিতে পারে।',\n fixes: [\n {\n title: 'client-only logic useEffect-এ নিন',\n description: 'mount হওয়ার পরে value compute করুন যাতে শুরুতে server/client এক থাকে।',\n snippet: \"const [mounted, setMounted] = useState(false);\\nuseEffect(() => setMounted(true), []);\\nif (!mounted) return null;\"\n },\n {\n title: 'initial render-এ random/Date এড়িয়ে চলুন',\n description: 'mount-এর পরে generate করুন, বা server থেকে pass করুন।'\n }\n ]\n }\n }\n }\n];\n","import type { ExplainOptions, ExplainResult, Pattern } from '../types.js';\nimport { simplifyStack } from './stack.js';\nimport { matchPattern } from './matcher.js';\nimport { patterns } from './patterns.js';\n\nexport function explainError(input: { message: string; stack?: string; name?: string; cause?: unknown }, options: ExplainOptions = {}): ExplainResult {\n const mode = options.mode ?? 'beginner';\n const language = options.language ?? 'en';\n\n const simplifiedStack = input.stack ? simplifyStack(input.stack) : undefined;\n\n const matched = matchPattern({ name: input.name, message: input.message }, patterns);\n const best: Pattern | undefined = matched?.pattern;\n\n if (best) {\n const localized = best.explanation[language];\n\n // mode currently only influences verbosity; keep it minimal for MVP\n const confidence = matched?.score ?? 0.6;\n\n return {\n input: {\n name: input.name,\n message: input.message,\n stack: input.stack,\n cause: input.cause\n },\n title: localized.title,\n whatHappened: localized.whatHappened,\n whyHappened: localized.whyHappened,\n suggestedFixes: localized.fixes,\n simplifiedStack,\n confidence,\n matchedPatternId: best.id\n };\n }\n\n const fallback = buildFallback(input.message, language, mode);\n return {\n input: {\n name: input.name,\n message: input.message,\n stack: input.stack,\n cause: input.cause\n },\n ...fallback,\n simplifiedStack,\n confidence: 0.2\n };\n}\n\nfunction buildFallback(message: string, language: 'en' | 'bn', mode: 'beginner' | 'pro') {\n if (language === 'bn') {\n return {\n title: 'অপরিচিত Error',\n whatHappened: `অ্যাপটি একটি error দিয়েছে: ${message}`,\n whyHappened:\n mode === 'pro'\n ? 'এই error-এর নির্দিষ্ট pattern ডাটাবেসে পাওয়া যায়নি। stack trace/কোড context দেখে root cause বের করতে হবে।'\n : 'এই error কেন হয়েছে সেটা নিশ্চিত না—কোড/ডাটা যাচাই করতে হবে।',\n suggestedFixes: [\n {\n title: 'Stack trace দেখুন',\n description: 'যেখানে error হয়েছে সেই file + line identify করুন।'\n },\n {\n title: 'Null/undefined guard দিন',\n description: 'object/property ব্যবহার করার আগে value আছে কিনা চেক করুন।',\n snippet: 'if (value == null) return;\\n// or\\nconst safe = obj?.prop;'\n }\n ]\n };\n }\n\n return {\n title: 'Unknown Error',\n whatHappened: `Your app threw an error: ${message}`,\n whyHappened:\n mode === 'pro'\n ? 'No known pattern matched this error. Use the stack trace and runtime context to identify the root cause.'\n : \"This error didn't match a known pattern. Check your data and the line where it happened.\",\n suggestedFixes: [\n {\n title: 'Inspect the stack trace',\n description: 'Identify the exact file and line where the error originated.'\n },\n {\n title: 'Add null/undefined guards',\n description: 'Check values before accessing properties or calling functions.',\n snippet: 'if (value == null) return;\\n// or\\nconst safe = obj?.prop;'\n }\n ]\n };\n}\n","import type { ExplainResult, ExplainerLanguage } from '../types.js';\n\nexport interface OverlayController {\n show: (result: ExplainResult) => void;\n destroy: () => void;\n}\n\nexport function createOverlay(opts: { language: ExplainerLanguage }): OverlayController {\n const root = document.createElement('div');\n root.id = 'auto-error-explainer-overlay';\n root.style.position = 'fixed';\n root.style.left = '0';\n root.style.right = '0';\n root.style.top = '0';\n root.style.zIndex = '2147483647';\n root.style.fontFamily = 'ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial';\n root.style.pointerEvents = 'none';\n\n const panel = document.createElement('div');\n panel.style.margin = '12px';\n panel.style.padding = '12px 14px';\n panel.style.background = 'rgba(17, 24, 39, 0.96)';\n panel.style.color = '#fff';\n panel.style.border = '1px solid rgba(255,255,255,0.12)';\n panel.style.borderRadius = '10px';\n panel.style.boxShadow = '0 10px 30px rgba(0,0,0,0.45)';\n panel.style.maxHeight = '50vh';\n panel.style.overflow = 'auto';\n panel.style.pointerEvents = 'auto';\n\n const header = document.createElement('div');\n header.style.display = 'flex';\n header.style.alignItems = 'center';\n header.style.justifyContent = 'space-between';\n header.style.gap = '10px';\n\n const title = document.createElement('div');\n title.style.fontWeight = '700';\n title.style.fontSize = '14px';\n\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.textContent = opts.language === 'bn' ? 'বন্ধ' : 'Close';\n closeBtn.style.fontSize = '12px';\n closeBtn.style.padding = '6px 10px';\n closeBtn.style.borderRadius = '8px';\n closeBtn.style.border = '1px solid rgba(255,255,255,0.18)';\n closeBtn.style.background = 'rgba(255,255,255,0.08)';\n closeBtn.style.color = '#fff';\n closeBtn.style.cursor = 'pointer';\n\n const body = document.createElement('div');\n body.style.marginTop = '10px';\n body.style.fontSize = '12px';\n body.style.lineHeight = '1.45';\n\n header.appendChild(title);\n header.appendChild(closeBtn);\n panel.appendChild(header);\n panel.appendChild(body);\n root.appendChild(panel);\n\n let mounted = false;\n const mount = () => {\n if (mounted) return;\n document.body.appendChild(root);\n mounted = true;\n };\n\n const hide = () => {\n if (!mounted) return;\n root.remove();\n mounted = false;\n };\n\n closeBtn.addEventListener('click', hide);\n\n return {\n show: (result: ExplainResult) => {\n mount();\n title.textContent = result.title;\n\n const fixes = result.suggestedFixes\n .map((f) => {\n const snippet = f.snippet ? `<pre style=\"margin:8px 0 0; padding:8px; background: rgba(0,0,0,0.35); border-radius: 8px; overflow:auto;\">${escapeHtml(f.snippet)}</pre>` : '';\n return `<div style=\"margin-top:10px; padding-top:10px; border-top: 1px solid rgba(255,255,255,0.10);\">\n <div style=\"font-weight:600;\">${escapeHtml(f.title)}</div>\n ${f.description ? `<div style=\"opacity:0.9; margin-top:4px;\">${escapeHtml(f.description)}</div>` : ''}\n ${snippet}\n </div>`;\n })\n .join('');\n\n const stackTop = result.simplifiedStack?.frames?.[0];\n const stackLine = stackTop?.file\n ? `<div style=\"margin-top:10px; opacity:0.9;\">${escapeHtml(stackTop.file)}:${stackTop.line ?? ''}</div>`\n : '';\n\n body.innerHTML = `\n <div style=\"opacity:0.9;\">${escapeHtml(result.whatHappened)}</div>\n <div style=\"margin-top:8px; opacity:0.9;\">${escapeHtml(result.whyHappened)}</div>\n ${stackLine}\n ${fixes}\n `;\n },\n destroy: () => {\n hide();\n closeBtn.removeEventListener('click', hide);\n }\n };\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#039;');\n}\n","import type { ExplainOptions, ExplainResult, ExplainerLanguage, ExplainerMode } from './types.js';\nimport { explainError } from './core/explain.js';\nimport { createOverlay, type OverlayController } from './ui/overlay.js';\n\nexport interface BrowserInitOptions {\n mode?: ExplainerMode;\n language?: ExplainerLanguage;\n overlay?: boolean;\n redact?: boolean;\n onExplained?: (result: ExplainResult) => void;\n}\n\nexport interface BrowserController {\n stop: () => void;\n}\n\nexport function initAutoErrorExplainer(options: BrowserInitOptions = {}): BrowserController {\n const mode = options.mode ?? 'beginner';\n const language = options.language ?? 'en';\n const overlayEnabled = options.overlay ?? true;\n\n const explainOpts: ExplainOptions = {\n mode,\n language,\n source: 'browser'\n };\n\n let overlay: OverlayController | undefined;\n if (overlayEnabled && typeof window !== 'undefined' && typeof document !== 'undefined') {\n overlay = createOverlay({ language });\n }\n\n const onResult = (result: ExplainResult) => {\n options.onExplained?.(result);\n overlay?.show(result);\n };\n\n const onError = (event: ErrorEvent) => {\n const message = event.message || 'Unknown error';\n const stack = (event.error && (event.error as any).stack) || undefined;\n const name = (event.error && (event.error as any).name) || undefined;\n\n const result = explainError({ message, stack, name }, explainOpts);\n onResult(result);\n };\n\n const onRejection = (event: PromiseRejectionEvent) => {\n const reason = event.reason;\n const message = reason?.message ? String(reason.message) : String(reason ?? 'Unhandled promise rejection');\n const stack = reason?.stack ? String(reason.stack) : undefined;\n const name = reason?.name ? String(reason.name) : undefined;\n\n const result = explainError({ message, stack, name, cause: reason }, explainOpts);\n onResult(result);\n };\n\n const originalConsoleError = console.error.bind(console);\n const patchedConsoleError = (...args: any[]) => {\n try {\n const first = args[0];\n const message = first instanceof Error ? first.message : String(first ?? 'console.error');\n const stack = first instanceof Error ? first.stack : undefined;\n const name = first instanceof Error ? first.name : undefined;\n\n const result = explainError({ message, stack, name, cause: args }, explainOpts);\n onResult(result);\n } catch {\n // ignore\n }\n originalConsoleError(...args);\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onRejection);\n console.error = patchedConsoleError;\n\n return {\n stop: () => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onRejection);\n console.error = originalConsoleError;\n overlay?.destroy();\n }\n };\n}\n"]}
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node