Skip to content

Commit 33adc5b

Browse files
author
vitaly.basaraba
committed
Featured: build codes
1 parent af98d53 commit 33adc5b

File tree

6 files changed

+120
-79
lines changed

6 files changed

+120
-79
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ logs/
1313
jspm_packages/
1414

1515
# Build directories
16-
dist/
1716
build/
1817

1918
# Webpack

cli.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env node
22
'use strict';
33

4-
const portUtil = require('./index.js');
4+
const portUtil = require('./dist/index.js');
55
const getThemArgs = require('get-them-args');
66
const args = getThemArgs(process.argv.slice(2));
77
const verbose = args.verbose || false;
@@ -33,12 +33,10 @@ Promise.all(
3333
range
3434
})
3535
.then((result) => {
36-
console.log(`Process on port ${current}`);
37-
verbose && console.log(result);
36+
verbose && console.log(`Process on port ${action} ${current}`);
3837
})
3938
.catch((error) => {
40-
console.log(`Could not process on port ${current}. ${error.message}.`);
41-
verbose && console.log(error);
39+
verbose && console.log(`Could not process on port ${current}. ${error.message}.`);
4240
});
4341
})
4442
);

dist/index.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.js

Lines changed: 104 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -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+\(CLOSED\)|\s+\(ESTABLISHED\)|\s+\(LISTEN\))/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
/**

package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{
22
"name": "port-client",
3-
"version": "1.3.0",
3+
"version": "1.4.1",
44
"description": "A powerful utility for managing processes on specified ports, including options for checking port status, killing processes, handling multiple ports, enabling interactive mode, and supporting graceful termination.",
5-
"main": "index.js",
5+
"main": "dist/index.js",
66
"scripts": {
7+
"build": "ncc build index.js -o dist",
8+
"build:prod": "ncc build index.js -o dist && terser dist/index.js -o dist/index.js --compress --mangle",
79
"test": "echo \"Error: no test specified\" && exit 1"
810
},
911
"repository": {
@@ -36,5 +38,9 @@
3638
"is-port-reachable": "^4.0.0",
3739
"readline": "^1.3.0",
3840
"shell-exec": "^1.0.2"
41+
},
42+
"devDependencies": {
43+
"@vercel/ncc": "^0.38.3",
44+
"terser": "^5.37.0"
3945
}
4046
}

pnpm-lock.yaml

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)