feat(smartnetwork): Add exclude option to findFreePort and skip excluded ports during search

This commit is contained in:
2025-09-12 18:26:56 +00:00
parent 6e59f0f5c0
commit 0f79773985
4 changed files with 37 additions and 1 deletions

View File

@@ -1,5 +1,12 @@
# Changelog # Changelog
## 2025-09-12 - 4.4.0 - feat(smartnetwork)
Add exclude option to findFreePort and skip excluded ports during search
- Add an 'exclude' array to IFindFreePortOptions so callers can specify ports to ignore when searching for a free port.
- Respect excluded ports in findFreePort for both random (randomize=true) and sequential searches so excluded ports are never returned.
- Add .claude/settings.local.json to include local permissions used for development/CI helpers.
## 2025-09-12 - 4.3.0 - feat(smartnetwork) ## 2025-09-12 - 4.3.0 - feat(smartnetwork)
Add randomizable port search and switch DNS resolution to @push.rocks/smartdns; export smartdns and update docs Add randomizable port search and switch DNS resolution to @push.rocks/smartdns; export smartdns and update docs

View File

@@ -99,6 +99,19 @@ const findFreePort = async () => {
// Find a random free port in range (useful to avoid port conflicts) // Find a random free port in range (useful to avoid port conflicts)
const randomPort = await network.findFreePort(3000, 3100, { randomize: true }); const randomPort = await network.findFreePort(3000, 3100, { randomize: true });
console.log(`🎲 Random free port: ${randomPort}`); console.log(`🎲 Random free port: ${randomPort}`);
// Exclude specific ports from the search
const portWithExclusions = await network.findFreePort(3000, 3100, {
exclude: [3000, 3001, 3005] // Skip these ports even if they're free
});
console.log(`🚫 Free port (excluding specific ports): ${portWithExclusions}`);
// Combine randomize with exclude options
const randomWithExclusions = await network.findFreePort(3000, 3100, {
randomize: true,
exclude: [3000, 3001, 3005]
});
console.log(`🎲🚫 Random free port (with exclusions): ${randomWithExclusions}`);
}; };
``` ```
@@ -333,6 +346,7 @@ interface SmartNetworkOptions {
interface IFindFreePortOptions { interface IFindFreePortOptions {
randomize?: boolean; // If true, returns a random free port instead of the first one randomize?: boolean; // If true, returns a random free port instead of the first one
exclude?: number[]; // Array of port numbers to exclude from the search
} }
interface Hop { interface Hop {

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartnetwork', name: '@push.rocks/smartnetwork',
version: '4.3.0', version: '4.4.0',
description: 'A toolkit for network diagnostics including speed tests, port availability checks, and more.' description: 'A toolkit for network diagnostics including speed tests, port availability checks, and more.'
} }

View File

@@ -31,6 +31,8 @@ export interface Hop {
export interface IFindFreePortOptions { export interface IFindFreePortOptions {
/** If true, selects a random available port within the range instead of the first one */ /** If true, selects a random available port within the range instead of the first one */
randomize?: boolean; randomize?: boolean;
/** Array of port numbers to exclude from the search */
exclude?: number[];
} }
export class SmartNetwork { export class SmartNetwork {
@@ -169,12 +171,20 @@ export class SmartNetwork {
throw new NetworkError('Start port must be less than or equal to end port', 'EINVAL'); throw new NetworkError('Start port must be less than or equal to end port', 'EINVAL');
} }
// Create a set of excluded ports for efficient lookup
const excludedPorts = new Set(options?.exclude || []);
// If randomize option is true, collect all available ports and select randomly // If randomize option is true, collect all available ports and select randomly
if (options?.randomize) { if (options?.randomize) {
const availablePorts: number[] = []; const availablePorts: number[] = [];
// Scan the range to find all available ports // Scan the range to find all available ports
for (let port = startPort; port <= endPort; port++) { for (let port = startPort; port <= endPort; port++) {
// Skip excluded ports
if (excludedPorts.has(port)) {
continue;
}
const isUnused = await this.isLocalPortUnused(port); const isUnused = await this.isLocalPortUnused(port);
if (isUnused) { if (isUnused) {
availablePorts.push(port); availablePorts.push(port);
@@ -192,6 +202,11 @@ export class SmartNetwork {
} else { } else {
// Default behavior: return the first available port (sequential search) // Default behavior: return the first available port (sequential search)
for (let port = startPort; port <= endPort; port++) { for (let port = startPort; port <= endPort; port++) {
// Skip excluded ports
if (excludedPorts.has(port)) {
continue;
}
const isUnused = await this.isLocalPortUnused(port); const isUnused = await this.isLocalPortUnused(port);
if (isUnused) { if (isUnused) {
return port; return port;