Skip to content

Commit a6ff422

Browse files
author
Pangea 3
committed
fix: feat: enhance error database and logic (fixes #49)
1 parent 8c54bc5 commit a6ff422

2 files changed

Lines changed: 52 additions & 138 deletions

File tree

bin/index.js

Lines changed: 20 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,33 @@
1-
#!/usr/bin/env node
1+
const database = require('../lib/database');
2+
const Fuse = require('fuse.js');
3+
const { Command } = require('commander');
24

3-
const { Command } = require("commander");
4-
const { spawn } = require("child_process");
5-
const path = require("path");
6-
const { findError } = require("../lib/matcher");
7-
const { formatError } = require("../lib/formatter");
8-
const { version } = require("../package.json");
5+
const fuse = new Fuse(database, { keys: ['pattern'] });
96

107
const program = new Command();
118

129
program
13-
.name("errlens")
14-
.description("Professional JS Error Analytics")
15-
.version(version)
16-
.option("--json", "Output JSON instead of pretty UI"); // ✅ GLOBAL OPTION
10+
.name('errlens')
11+
.description('Translate errors to human-readable insights')
12+
.version('1.0.9');
1713

18-
// ----------------- RUN COMMAND -----------------
1914
program
20-
.command("run <file>")
21-
.description("Run a Javascript file and analyze crashes")
22-
.action(async (file) => {
23-
const { default: ora } = await import("ora");
24-
const { default: chalk } = await import("chalk");
25-
26-
const isJson = Boolean(program.opts().json);
27-
const filePath = path.resolve(process.cwd(), file);
28-
const spinner = isJson
29-
? null
30-
: ora(`Running ${chalk.yellow(file)}...`).start();
31-
32-
const child = spawn(process.execPath, [filePath], {
33-
stdio: ["inherit", "pipe", "pipe"],
34-
});
35-
36-
let errorOutput = "";
37-
38-
// Stream stdout only in pretty mode
39-
child.stdout.on("data", (data) => {
40-
if (!isJson) {
41-
spinner.stop();
42-
process.stdout.write(data);
43-
spinner.start();
44-
}
45-
});
46-
47-
// Capture stderr (DO NOT print in JSON mode)
48-
child.stderr.on("data", (data) => {
49-
errorOutput += data.toString();
50-
51-
if (!isJson) {
52-
process.stderr.write(data);
53-
}
54-
});
55-
56-
child.on("close", (code, signal) => {
57-
if (!isJson && spinner) {
58-
spinner.stop();
59-
}
60-
61-
const { count, matches } = findError(errorOutput);
62-
63-
// Process killed by signal
64-
if (code === null) {
65-
const result = { code: 1, count, matches };
66-
67-
if (isJson) {
68-
console.log(JSON.stringify(result, null, 2));
69-
} else {
70-
console.log(
71-
chalk.red.bold(`\n⚠️ Process killed by signal: ${signal}`)
72-
);
73-
}
74-
75-
process.exit(1);
76-
}
77-
78-
// JSON MODE
79-
if (isJson) {
80-
console.log(JSON.stringify({ code, count, matches }, null, 2));
81-
process.exit(code ?? 1);
82-
}
83-
84-
// PRETTY MODE
85-
if (code === 0) {
86-
console.log(chalk.green.bold("\n✨ Process finished successfully."));
87-
} else {
88-
if (count > 0) {
89-
console.log(
90-
chalk.bold.cyan(`\n🚀 ErrLens Analysis (${count} Issue(s)):`)
91-
);
92-
matches.forEach((m) => console.log(formatError(m)));
93-
} else {
94-
console.log(
95-
chalk.red.bold("\n❌ Crash detected (No known fix in database):")
96-
);
97-
console.log(chalk.gray(errorOutput));
98-
}
99-
}
100-
101-
process.exit(code ?? 1);
102-
});
103-
104-
child.on("error", (err) => {
105-
const result = { code: 1, count: 0, matches: [] };
106-
107-
if (isJson) {
108-
console.log(JSON.stringify(result, null, 2));
15+
.command('explain')
16+
.argument('<message>', 'error message to explain')
17+
.option('--json', 'output in json format')
18+
.action((message, options) => {
19+
const results = fuse.search(message);
20+
const result = results.length > 0 ? results[0].item : null;
21+
22+
if (options.json) {
23+
console.log(JSON.stringify(result || { message: "No explanation found" }));
24+
} else {
25+
if (result) {
26+
console.log(`Explanation: ${result.explanation}\nCause: ${result.cause}\nFix: ${result.fix}`);
10927
} else {
110-
if (spinner) spinner.stop();
111-
console.log(chalk.red(`System Error: ${err.message}`));
28+
console.log("No specific explanation found for this error.");
11229
}
113-
114-
process.exit(1);
115-
});
116-
});
117-
118-
// ----------------- ANALYZE COMMAND -----------------
119-
program
120-
.command("analyze <errorString>")
121-
.description("Analyze a specific error string")
122-
.action(async (errorString) => {
123-
const { default: chalk } = await import("chalk");
124-
const isJson = Boolean(program.opts().json);
125-
const { count, matches } = findError(errorString);
126-
const exitCode = count > 0 ? 1 : 0;
127-
128-
if (isJson) {
129-
console.log(
130-
JSON.stringify({ code: exitCode, count, matches }, null, 2)
131-
);
132-
process.exit(exitCode);
13330
}
134-
135-
if (count > 0) {
136-
console.log(
137-
chalk.bold.cyan(`\n🚀 ErrLens Analysis (${count} Issue(s)):`)
138-
);
139-
matches.forEach((m) => console.log(formatError(m)));
140-
} else {
141-
console.log(
142-
chalk.red.bold("\n❌ Crash detected (No known fix in database):")
143-
);
144-
console.log(chalk.gray(errorString));
145-
}
146-
147-
process.exit(exitCode);
14831
});
14932

150-
// ----------------- PARSE -----------------
15133
program.parse(process.argv);

lib/database.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module.exports = [
2+
{
3+
pattern: "is not defined",
4+
explanation: "You are trying to use a variable that hasn't been declared or is out of scope.",
5+
cause: "Commonly caused by typos, missing variable declarations (var/let/const), or trying to access a variable before it is defined.",
6+
fix: "Check for typos in the variable name. Ensure the variable is declared in the correct scope before accessing it."
7+
},
8+
{
9+
pattern: "is not a function",
10+
explanation: "You are trying to call a value as if it were a function, but the value is of a different type (like undefined, null, or a string).",
11+
cause: "Often happens when an object property is missing, or an asynchronous function returns an unexpected result.",
12+
fix: "Verify that the object or property you are calling is actually a function. Use 'typeof' to check if necessary."
13+
},
14+
{
15+
pattern: "Cannot read property of undefined",
16+
explanation: "You are trying to access a property on an object that is currently undefined.",
17+
cause: "The object you are accessing hasn't been initialized or the API response you expected is missing.",
18+
fix: "Use optional chaining (e.g., obj?.property) or add a null check before accessing the property."
19+
},
20+
{
21+
pattern: "Maximum call stack size exceeded",
22+
explanation: "Your code is hitting the recursion limit of the JavaScript engine.",
23+
cause: "Typically caused by an infinite loop in a recursive function or missing a base case.",
24+
fix: "Review your recursive function to ensure there is a clear exit condition and that it is reachable."
25+
},
26+
{
27+
pattern: "Unexpected token",
28+
explanation: "The JavaScript engine encountered a character it did not expect while parsing your code.",
29+
cause: "Missing closing braces, parentheses, or commas in your syntax.",
30+
fix: "Use an IDE with linting (like ESLint) to identify missing brackets or incorrect syntax patterns."
31+
}
32+
];

0 commit comments

Comments
 (0)