@@ -14,25 +14,25 @@ class PortClient {
1414 */
1515 constructor ( ports , {
1616 method = 'tcp' ,
17- action = 'check' , // Default action is 'check'
17+ action = 'check' ,
1818 interactive = false ,
1919 dryRun = false ,
2020 verbose = false ,
2121 graceful = false ,
2222 filter = null ,
2323 range = null ,
24- speed = 'safe' , // Default speed is 'safe'
24+ speed = 'safe' ,
2525 } = { } ) {
2626 this . ports = ports ;
2727 this . method = method ;
28- this . action = action ; // Action flag to decide whether to check, kill, or show existence
28+ this . action = action ;
2929 this . interactive = interactive ;
3030 this . dryRun = dryRun ;
3131 this . verbose = verbose ;
3232 this . graceful = graceful ;
3333 this . filter = filter ;
3434 this . range = range ;
35- this . speed = speed ; // Store the speed option
35+ this . speed = speed ;
3636 this . platform = process . platform ;
3737 }
3838
@@ -73,18 +73,16 @@ class PortClient {
7373 }
7474
7575 if ( this . dryRun ) {
76- console . log ( `Dry run: Ports to operate on - ${ parsedPorts . join ( ', ' ) } ` ) ;
76+ this . success ( `Dry run: Ports to operate on - ${ parsedPorts . join ( ', ' ) } ` ) ;
7777 return ;
7878 }
7979
80- // Interactive mode: Display active ports and allow user to select
8180 if ( this . interactive ) {
8281 const activePorts = await this . listActivePorts ( ) ;
8382 const selectedPorts = await this . promptUserToSelectPorts ( activePorts ) ;
8483 return this . handlePorts ( selectedPorts ) ;
8584 }
8685
87- // Handle the ports based on the action
8886 return this . handlePorts ( parsedPorts ) ;
8987 }
9088
@@ -96,8 +94,8 @@ class PortClient {
9694 const command = this . platform === 'win32'
9795 ? 'netstat -nao'
9896 : ( this . speed === 'fast'
99- ? `lsof -i :${ this . ports } ` // Use fast option
100- : 'lsof -i -P' ) ; // Default to safe option
97+ ? `lsof -i :${ this . ports } `
98+ : 'lsof -i -P -n ' ) ;
10199
102100 try {
103101 const { stdout } = await sh ( command ) ;
@@ -130,14 +128,11 @@ class PortClient {
130128 * @returns {string[] } The parsed active ports.
131129 */
132130 parseUnixPorts ( lines ) {
133- const regex = new RegExp ( `:${ this . method === 'udp' ? 'udp' : 'tcp' } :(\\d+)` , 'gm' ) ;
134- return lines . reduce ( ( acc , line ) => {
135- const match = line . match ( regex ) ;
136- if ( match && match [ 1 ] && ! acc . includes ( match [ 1 ] ) ) {
137- acc . push ( match [ 1 ] ) ;
138- }
139- return acc ;
140- } , [ ] ) ;
131+
132+ const regex = / (?< = : \d { 1 , 5 } ) - > | \b \d { 1 , 5 } (? = - > | \s + \( C L O S E D \) | \s + \( E S T A B L I S H E D \) | \s + \( L I S T E N \) ) / g;
133+
134+ return lines . flatMap ( line => line . match ( regex ) ) . filter ( Boolean ) ;
135+
141136 }
142137
143138 /**
@@ -150,7 +145,7 @@ class PortClient {
150145 const rl = readline . createInterface ( { input : process . stdin , output : process . stdout } ) ;
151146
152147 activePorts . forEach ( ( port , index ) => {
153- console . log ( `${ index + 1 } . ${ port } ` ) ;
148+ this . success ( `${ index + 1 } . ${ port } ` ) ;
154149 } ) ;
155150
156151 rl . question ( 'Select ports to operate on (comma-separated indices): ' , ( answer ) => {
@@ -163,24 +158,22 @@ class PortClient {
163158 }
164159
165160 /**
166- * Handles the operation (check, isExist, or kill) for the given ports.
167- * @param {number[] } ports - The ports to handle.
168- * @returns {Promise<void> }
161+ * Handles the action on a list of ports based on the specified action type.
162+ *
163+ * @param {number[] } ports - The list of port numbers to act upon.
164+ * @returns {Promise } The result of the action performed.
169165 */
170166 async handlePorts ( ports ) {
171- if ( this . action === 'check' ) {
172- // Show info about the port
173- return this . showPortInfo ( ports ) ;
174- }
167+ switch ( this . action ) {
168+ case 'check' :
169+ case 'isExist' :
170+ return this . showPortInfo ( ports ) ;
175171
176- if ( this . action === 'isExist' ) {
177- // Just check if the port exists
178- return this . showPortInfo ( ports ) ;
179- }
172+ case 'kill' :
173+ return this . killPorts ( ports ) ;
180174
181- if ( this . action === 'kill' ) {
182- // Kill the port
183- return this . killPorts ( ports ) ;
175+ default :
176+ throw new Error ( `Unknown action: ${ this . action } ` ) ;
184177 }
185178 }
186179
@@ -192,35 +185,58 @@ class PortClient {
192185
193186 async isExistNormal ( port ) {
194187 const activePorts = await this . listActivePorts ( ) ;
195- console . log ( activePorts )
196188
197189 return activePorts . includes ( String ( port ) ) ;
198190 }
199191
200192 /**
201- * Shows information about the given ports.
202- * @param {number[] } ports - The ports to check.
193+ * Logs a success message in green.
194+ *
195+ * @param {string } message - The success message to log.
196+ * @returns {void }
197+ */
198+ success ( message ) {
199+ console . log ( '\x1b[32m%s\x1b[0m' , `${ message } ` ) ;
200+ }
201+
202+ /**
203+ * Logs an error message in red.
204+ *
205+ * @param {string } message - The error message to log.
206+ * @returns {void }
207+ */
208+ error ( message ) {
209+ console . log ( '\x1b[31m%s\x1b[0m' , `${ message } ` ) ;
210+ }
211+
212+ /**
213+ * Checks and logs the status of each port, indicating whether it is active or not.
214+ *
215+ * @param {number[] } ports - An array of port numbers to check for activity.
203216 */
204217 async showPortInfo ( ports ) {
205218 for ( const port of ports ) {
206- if ( this . speed === 'fast' ) {
207- try {
208- const isExit = await this . isExistFast ( port ) ;
209- console . log ( isExit ? `Port ${ port } is active.` : `Port ${ port } is not active.` ) ;
210- } catch ( error ) {
211- console . error ( `Error checking port ${ port } : ${ error . message } ` ) ;
212- }
213- } else {
214- try {
215- const isExit = await this . isExistNormal ( port ) ;
216- console . log ( isExit ? `Port ${ port } is active.` : `Port ${ port } is not active.` ) ;
217- } catch ( error ) {
218- console . error ( `Error retrieving active ports: ${ error . message } ` ) ;
219- }
219+ try {
220+ const isActive = await this . checkPortStatus ( port ) ;
221+
222+ this . success ( isActive ? `Port ${ port } is active.` : `Port ${ port } is not active.` ) ;
223+ } catch ( error ) {
224+ this . error ( `Error checking port ${ port } : ${ error . message } ` ) ;
220225 }
221226 }
222227 }
223228
229+ /**
230+ * Checks whether a given port is active based on the current speed setting.
231+ *
232+ * @param {number } port - The port number to check.
233+ * @returns {Promise<boolean> } A promise that resolves to a boolean indicating whether the port is active.
234+ */
235+ async checkPortStatus ( port ) {
236+ const checkMethod = this . speed === 'fast' ? this . isExistFast : this . isExistNormal ;
237+ return await checkMethod . call ( this , port ) ;
238+ }
239+
224240 /**
225241 * Kills the specified ports.
226242 * @param {number[] } ports - The ports to kill.
@@ -235,9 +251,9 @@ class PortClient {
235251
236252 this . log ( `Executing: ${ command } ` ) ;
237253 const result = await sh ( command ) ;
238- this . log ( `Successfully killed port ${ port } : ${ result . stdout } ` ) ;
254+ this . success ( `Successfully killed port ${ port } ${ result . stdout } ` ) ;
239255 } catch ( error ) {
240- console . error ( `Failed to kill port ${ port } : ${ error . message } ` ) ;
256+ this . error ( `Failed to kill port ${ port } : ${ error . message } ` ) ;
241257 }
242258 }
243259 }
@@ -267,32 +283,54 @@ class PortClient {
267283 }
268284
269285 /**
270- * Gets the Unix command to kill a port.
271- * @param {number } port - The port to kill.
272- * @param {string } method - The protocol (tcp/udp).
273- * @param {boolean } graceful - Whether to use a graceful kill.
274- * @returns {string } The Unix kill command.
286+ * Constructs the Unix command to kill a process running on a specified port.
287+ * The command will either gracefully or forcefully terminate the process, depending on the `graceful` parameter.
288+ *
289+ * @param {number } port - The port number where the process is running.
290+ * @param {string } [method='tcp'] - The method (protocol) for the command (e.g., 'tcp' or 'udp'). Defaults to 'tcp'.
291+ * @param {boolean } [graceful=false] - Whether to send a graceful kill signal (`true`) or a forceful one (`false`). Defaults to `false` (forceful kill).
292+ * @returns {Promise<string> } The full Unix command string to kill the process.
293+ * @throws {Error } Throws an error if no process is found running on the specified port.
275294 */
276295 async getUnixKillCommand ( port , method = 'tcp' , graceful = false ) {
277- const baseCommand = `lsof -i ${ method } :${ port } | grep ${ method . toUpperCase ( ) } | awk '{print $2}' | xargs` ;
278-
296+ const baseCommand = this . buildBaseCommand ( method , port ) ;
279297 const killCommand = graceful ? 'kill' : 'kill -9' ;
280298
281299 try {
282- let existProccess = null ;
283- if ( this . speed === 'fast' ) {
284- existProccess = await this . isExistFast ( port ) ;
285- } else {
286- existProccess = await this . isExistNormal ( port ) ;
287- }
300+ const processExists = await this . checkIfProcessExists ( port ) ;
288301
289- if ( ! existProccess ) throw new Error ( 'No process running on port' ) ;
302+ if ( ! processExists ) {
303+ throw new Error ( 'No process running on port' ) ;
304+ }
290305
291306 return `${ baseCommand } ${ killCommand } ` ;
292307 } catch ( error ) {
293- throw new Error ( `Failed to get Unix kill command: ${ error . message } ` ) ;
308+ throw new Error ( `${ error . message } ` ) ;
294309 }
295310 }
311+
312+ /**
313+ * Builds the base command for listing the process associated with a port and method.
314+ *
315+ * @param {string } method - The method (protocol) for the command (e.g., 'tcp' or 'udp').
316+ * @param {number } port - The port number where the process is running.
317+ * @returns {string } The base command to find the process ID (PID) of the process running on the specified port and protocol.
318+ */
319+ buildBaseCommand ( method , port ) {
320+ return `lsof -i ${ method } :${ port } | grep ${ method . toUpperCase ( ) } | awk '{print $2}' | xargs` ;
321+ }
322+
323+ /**
324+ * Checks if a process is running on the specified port by using either a fast or normal check based on the current speed setting.
325+ *
326+ * @param {number } port - The port number where the process is running.
327+ * @returns {Promise<boolean> } A boolean indicating whether a process is running on the specified port.
328+ */
329+ async checkIfProcessExists ( port ) {
330+ const isFastCheck = this . speed === 'fast' ;
331+ const checkMethod = isFastCheck ? this . isExistFast : this . isExistNormal ;
332+ return await checkMethod . call ( this , port ) ;
333+ }
296334}
297335
298336/**
0 commit comments