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
107const program = new Command ( ) ;
118
129program
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 -----------------
1914program
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 -----------------
15133program . parse ( process . argv ) ;
0 commit comments