Compare commits

...

4 Commits

15 changed files with 406 additions and 231 deletions

View File

@ -0,0 +1,66 @@
name: Default (not tags)
on:
push:
tags-ignore:
- '**'
env:
IMAGE: code.foss.global/host.today/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
jobs:
security:
runs-on: ubuntu-latest
continue-on-error: true
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Install pnpm and npmci
run: |
pnpm install -g pnpm
pnpm install -g @ship.zone/npmci
- name: Run npm prepare
run: npmci npm prepare
- name: Audit production dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --prod
continue-on-error: true
- name: Audit development dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --dev
continue-on-error: true
test:
if: ${{ always() }}
needs: security
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Test stable
run: |
npmci node install stable
npmci npm install
npmci npm test
- name: Test build
run: |
npmci node install stable
npmci npm install
npmci npm build

View File

@ -0,0 +1,124 @@
name: Default (tags)
on:
push:
tags:
- '*'
env:
IMAGE: code.foss.global/host.today/ht-docker-node:npmci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
jobs:
security:
runs-on: ubuntu-latest
continue-on-error: true
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @ship.zone/npmci
npmci npm prepare
- name: Audit production dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --prod
continue-on-error: true
- name: Audit development dependencies
run: |
npmci command npm config set registry https://registry.npmjs.org
npmci command pnpm audit --audit-level=high --dev
continue-on-error: true
test:
if: ${{ always() }}
needs: security
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @ship.zone/npmci
npmci npm prepare
- name: Test stable
run: |
npmci node install stable
npmci npm install
npmci npm test
- name: Test build
run: |
npmci node install stable
npmci npm install
npmci npm build
release:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @ship.zone/npmci
npmci npm prepare
- name: Release
run: |
npmci node install stable
npmci npm publish
metadata:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
container:
image: ${{ env.IMAGE }}
continue-on-error: true
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
pnpm install -g pnpm
pnpm install -g @ship.zone/npmci
npmci npm prepare
- name: Code quality
run: |
npmci command npm install -g typescript
npmci npm install
- name: Trigger
run: npmci trigger
- name: Build docs and upload artifacts
run: |
npmci node install stable
npmci npm install
pnpm install -g @git.zone/tsdoc
npmci command tsdoc
continue-on-error: true

3
.gitignore vendored
View File

@ -3,7 +3,6 @@
# artifacts # artifacts
coverage/ coverage/
public/ public/
pages/
# installs # installs
node_modules/ node_modules/
@ -17,4 +16,4 @@ node_modules/
dist/ dist/
dist_*/ dist_*/
# custom #------# custom

View File

@ -1,141 +0,0 @@
# gitzone ci_default
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache:
paths:
- .npmci_cache/
key: '$CI_BUILD_STAGE'
stages:
- security
- test
- release
- metadata
before_script:
- npm install -g @shipzone/npmci
# ====================
# security stage
# ====================
mirror:
stage: security
script:
- npmci git mirror
only:
- tags
tags:
- lossless
- docker
- notpriv
auditProductionDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security
script:
- npmci npm prepare
- npmci command npm install --production --ignore-scripts
- npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high --only=prod --production
tags:
- docker
allow_failure: true
auditDevDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security
script:
- npmci npm prepare
- npmci command npm install --ignore-scripts
- npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high --only=dev
tags:
- docker
allow_failure: true
# ====================
# test stage
# ====================
testStable:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
testBuild:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
release:
stage: release
script:
- npmci node install stable
- npmci npm publish
only:
- tags
tags:
- lossless
- docker
- notpriv
# ====================
# metadata stage
# ====================
codequality:
stage: metadata
allow_failure: true
only:
- tags
script:
- npmci command npm install -g tslint typescript
- npmci npm prepare
- npmci npm install
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
tags:
- lossless
- docker
- priv
trigger:
stage: metadata
script:
- npmci trigger
only:
- tags
tags:
- lossless
- docker
- notpriv
pages:
stage: metadata
script:
- npmci node install lts
- npmci command npm install -g @git.zone/tsdoc
- npmci npm prepare
- npmci npm install
- npmci command tsdoc
tags:
- lossless
- docker
- notpriv
only:
- tags
artifacts:
expire_in: 1 week
paths:
- public
allow_failure: true

View File

@ -1,5 +1,22 @@
# Changelog # Changelog
## 2025-04-28 - 3.0.5 - fix(core)
Improve logging and error handling by introducing custom error classes and a global logging interface while refactoring network diagnostics methods.
- Added custom error classes (NetworkError, TimeoutError) for network operations.
- Introduced a global logging interface to replace direct console logging.
- Updated CloudflareSpeed and SmartNetwork classes to use getLogger for improved error reporting.
- Disabled connection pooling in HTTP requests to prevent listener accumulation.
## 2025-04-28 - 3.0.4 - fix(ci/config)
Improve CI workflows, update project configuration, and clean up code formatting
- Added new Gitea workflow files (default_nottags.yaml and default_tags.yaml) to replace GitLab CI
- Updated package.json with new buildDocs script, revised homepage URL, bug tracking info, and pnpm overrides
- Refined code formatting in TypeScript files, including improved error handling in Cloudflare speed tests and consistent callback structure
- Enhanced tsconfig.json by adding baseUrl and paths for better module resolution
- Introduced readme.plan.md outlining future improvements and feature enhancements
## 2025-04-28 - 3.0.3 - fix(deps) ## 2025-04-28 - 3.0.3 - fix(deps)
Update dependency namespaces and bump package versions in CI configuration and source imports Update dependency namespaces and bump package versions in CI configuration and source imports

View File

@ -1,6 +1,6 @@
{ {
"name": "@push.rocks/smartnetwork", "name": "@push.rocks/smartnetwork",
"version": "3.0.3", "version": "3.0.5",
"private": false, "private": false,
"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.",
"main": "dist_ts/index.js", "main": "dist_ts/index.js",
@ -10,7 +10,8 @@
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"test": "(tstest test/)", "test": "(tstest test/)",
"build": "(tsbuild --web --allowimplicitany)" "build": "(tsbuild --web --allowimplicitany)",
"buildDocs": "tsdoc"
}, },
"devDependencies": { "devDependencies": {
"@git.zone/tsbuild": "^2.1.61", "@git.zone/tsbuild": "^2.1.61",
@ -56,10 +57,16 @@
"network utility", "network utility",
"TypeScript" "TypeScript"
], ],
"homepage": "https://code.foss.global/push.rocks/smartnetwork", "homepage": "https://code.foss.global/push.rocks/smartnetwork#readme",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://code.foss.global/push.rocks/smartnetwork.git" "url": "https://code.foss.global/push.rocks/smartnetwork.git"
}, },
"packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6" "packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6",
"bugs": {
"url": "https://code.foss.global/push.rocks/smartnetwork/issues"
},
"pnpm": {
"overrides": {}
}
} }

View File

@ -1,4 +1,5 @@
# @push.rocks/smartnetwork # @push.rocks/smartnetwork
network diagnostics network diagnostics
## Install ## Install
@ -58,7 +59,7 @@ const checkLocalPort = async (port: number) => {
} }
}; };
checkLocalPort(8080); // Example port number checkLocalPort(8080); // Example port number
``` ```
### Checking Remote Port Availability ### Checking Remote Port Availability
@ -75,7 +76,7 @@ const checkRemotePort = async (hostname: string, port: number) => {
} }
}; };
checkRemotePort('example.com', 443); // Checking HTTPS port on example.com checkRemotePort('example.com', 443); // Checking HTTPS port on example.com
``` ```
### Using Ping ### Using Ping
@ -131,7 +132,7 @@ These examples offer a glimpse into the module's utility in real-world scenarios
## License and Legal Information ## License and Legal Information
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file. **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

47
readme.plan.md Normal file
View File

@ -0,0 +1,47 @@
# Plan to Enhance Code Quality, Feature Set & Documentation
This plan focuses on three pillars to elevate `@push.rocks/smartnetwork`: 1) Code Quality, 2) Feature Enhancements, and 3) Documentation.
## 1. Code Quality Improvements
- Enable strict TypeScript (`strict`, `noImplicitAny`, `strictNullChecks`).
- Enforce linting (ESLint) and formatting (Prettier) with pre-commit hooks.
- Audit and refactor core modules for:
- Clear separation of concerns (IO, business logic, helpers).
- Removal of duplicated logic and dead code.
- Consistent use of async/await and error propagation.
- Introduce custom error classes (e.g., `NetworkError`, `TimeoutError`) for predictable failure handling.
- Augment logging support via injectable logger interface.
- Establish a baseline of ≥90% unit-test coverage and enforce via CI.
## 2. Feature Enhancements
- Expand diagnostics:
- Traceroute functionality with hop-by-hop latency.
- DNS lookup (A, AAAA, MX records).
- HTTP(s) endpoint health check (status codes, headers, latency).
- Improve existing methods:
- `getSpeed`: allow configurable test duration and parallel streams.
- `ping`: add statistical summary (min, max, stddev) and continuous mode.
- `isRemotePortAvailable`: support TCP/UDP checks with timeout and retry.
- Introduce plugin architecture:
- Define `Plugin` interface for third-party extensions.
- Enable runtime registration/unregistration.
- Provide sample plugins (e.g., custom ping strategies, alternate speed providers).
- Optional in-memory caching with TTL for expensive calls (`getPublicIps`, `getGateways`).
## 3. Documentation & Examples
- Upgrade README:
- Detailed API reference with method signatures and option parameters.
- Real-world usage snippets and full example projects.
- Add TSDoc comments to all public classes, methods, and types.
- Create a `docs/` folder with:
- Getting Started guide.
- Advanced topics (plugin development, custom error handling).
- FAQ and troubleshooting section.
- Integrate TypeDoc for automated documentation site generation.
- Update `CONTRIBUTING.md` and `CHANGELOG.md` to reflect development and release practices.
## Next Steps
1. Review and prioritize high-impact items per pillar.
2. Kick off Phase 1 (Code Quality) with linting, TS config, and core refactor.
3. Schedule sprints for Feature and Documentation phases.
4. Configure CI pipeline to enforce quality gates and publish docs.

View File

@ -20,6 +20,6 @@ tap.test('should state when a ping is not alive ', async () => {
tap.test('should send a ping to an IP', async () => { tap.test('should send a ping to an IP', async () => {
await expectAsync(testSmartnetwork.ping('192.168.186.999')).property('alive').toBeFalse(); await expectAsync(testSmartnetwork.ping('192.168.186.999')).property('alive').toBeFalse();
}) });
tap.start(); tap.start();

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartnetwork', name: '@push.rocks/smartnetwork',
version: '3.0.3', version: '3.0.5',
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.'
} }

20
ts/errors.ts Normal file
View File

@ -0,0 +1,20 @@
/**
* Custom error classes for network operations
*/
export class NetworkError extends Error {
public code?: string;
constructor(message?: string, code?: string) {
super(message);
this.name = 'NetworkError';
this.code = code;
Object.setPrototypeOf(this, new.target.prototype);
}
}
export class TimeoutError extends NetworkError {
constructor(message?: string) {
super(message, 'ETIMEOUT');
this.name = 'TimeoutError';
Object.setPrototypeOf(this, new.target.prototype);
}
}

30
ts/logging.ts Normal file
View File

@ -0,0 +1,30 @@
/**
* Injectable logging interface and global logger
*/
export interface Logger {
/** Debug-level messages */
debug?(...args: unknown[]): void;
/** Informational messages */
info(...args: unknown[]): void;
/** Warning messages */
warn?(...args: unknown[]): void;
/** Error messages */
error(...args: unknown[]): void;
}
let globalLogger: Logger = console;
/**
* Replace the global logger implementation
* @param logger Custom logger adhering to Logger interface
*/
export function setLogger(logger: Logger): void {
globalLogger = logger;
}
/**
* Retrieve the current global logger
*/
export function getLogger(): Logger {
return globalLogger;
}

View File

@ -1,4 +1,6 @@
import * as plugins from './smartnetwork.plugins.js'; import * as plugins from './smartnetwork.plugins.js';
import { getLogger } from './logging.js';
import { NetworkError, TimeoutError } from './errors.js';
import * as stats from './helpers/stats.js'; import * as stats from './helpers/stats.js';
export class CloudflareSpeed { export class CloudflareSpeed {
@ -49,8 +51,8 @@ export class CloudflareSpeed {
measurements.push(response[4] - response[0] - response[6]); measurements.push(response[4] - response[0] - response[6]);
}, },
(error) => { (error) => {
console.log(`Error: ${error}`); getLogger().error('Error measuring latency:', error);
} },
); );
} }
@ -73,8 +75,8 @@ export class CloudflareSpeed {
measurements.push(await this.measureSpeed(bytes, transferTime)); measurements.push(await this.measureSpeed(bytes, transferTime));
}, },
(error) => { (error) => {
console.log(`Error: ${error}`); getLogger().error('Error measuring download chunk:', error);
} },
); );
} }
@ -91,8 +93,8 @@ export class CloudflareSpeed {
measurements.push(await this.measureSpeed(bytes, transferTime)); measurements.push(await this.measureSpeed(bytes, transferTime));
}, },
(error) => { (error) => {
console.log(`Error: ${error}`); getLogger().error('Error measuring upload chunk:', error);
} },
); );
} }
@ -104,15 +106,16 @@ export class CloudflareSpeed {
} }
public async fetchServerLocations(): Promise<{ [key: string]: string }> { public async fetchServerLocations(): Promise<{ [key: string]: string }> {
const res = JSON.parse(await this.get('speed.cloudflare.com', '/locations')); const res = JSON.parse(
await this.get('speed.cloudflare.com', '/locations'),
return res.reduce((data: any, optionsArg: { iata: string; city: string }) => { ) as Array<{ iata: string; city: string }>;
// Bypass prettier "no-assign-param" rules return res.reduce(
const data1 = data; (data: Record<string, string>, optionsArg) => {
data[optionsArg.iata] = optionsArg.city;
data1[optionsArg.iata] = optionsArg.city; return data;
return data1; },
}, {}); {} as Record<string, string>,
);
} }
public async get(hostname: string, path: string): Promise<string> { public async get(hostname: string, path: string): Promise<string> {
@ -122,6 +125,8 @@ export class CloudflareSpeed {
hostname, hostname,
path, path,
method: 'GET', method: 'GET',
// disable connection pooling to avoid listener accumulation
agent: false,
}, },
(res) => { (res) => {
const body: Array<Buffer> = []; const body: Array<Buffer> = [];
@ -135,10 +140,10 @@ export class CloudflareSpeed {
reject(e); reject(e);
} }
}); });
req.on('error', (err) => { req.on('error', (err: Error & { code?: string }) => {
reject(err); reject(new NetworkError(err.message, err.code));
}); });
} },
); );
req.end(); req.end();
@ -179,33 +184,36 @@ export class CloudflareSpeed {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
started = plugins.perfHooks.performance.now(); started = plugins.perfHooks.performance.now();
const req = plugins.https.request(options, (res) => { // disable connection pooling to avoid listener accumulation across requests
const reqOptions = { ...options, agent: false };
const req = plugins.https.request(reqOptions, (res) => {
res.once('readable', () => { res.once('readable', () => {
ttfb = plugins.perfHooks.performance.now(); ttfb = plugins.perfHooks.performance.now();
}); });
res.on('data', () => {}); res.on('data', () => {});
res.on('end', () => { res.on('end', () => {
ended = plugins.perfHooks.performance.now(); ended = plugins.perfHooks.performance.now();
resolve([ resolve([
started, started,
dnsLookup, dnsLookup,
tcpHandshake, tcpHandshake,
sslHandshake, sslHandshake,
ttfb, ttfb,
ended, ended,
parseFloat(res.headers['server-timing'].slice(22) as any), parseFloat((res.headers['server-timing'] as string).slice(22)),
]); ]);
}); });
}); });
req.on('socket', (socket) => { // Listen for timing events once per new socket
socket.on('lookup', () => { req.once('socket', (socket) => {
socket.once('lookup', () => {
dnsLookup = plugins.perfHooks.performance.now(); dnsLookup = plugins.perfHooks.performance.now();
}); });
socket.on('connect', () => { socket.once('connect', () => {
tcpHandshake = plugins.perfHooks.performance.now(); tcpHandshake = plugins.perfHooks.performance.now();
}); });
socket.on('secureConnect', () => { socket.once('secureConnect', () => {
sslHandshake = plugins.perfHooks.performance.now(); sslHandshake = plugins.perfHooks.performance.now();
}); });
}); });
@ -238,20 +246,14 @@ export class CloudflareSpeed {
text text
.split('\n') .split('\n')
.map((i) => { .map((i) => {
const j = i.split('='); const parts = i.split('=');
return [parts[0], parts[1]];
return [j[0], j[1]];
}) })
.reduce((data: any, [k, v]) => { .reduce((data: Record<string, string>, [k, v]) => {
if (v === undefined) return data; if (v === undefined) return data;
data[k] = v;
// Bypass prettier "no-assign-param" rules return data;
const data1 = data; }, {} as Record<string, string>);
// Object.fromEntries is only supported by Node.js 12 or newer
data1[k] = v;
return data1;
}, {});
return this.get('speed.cloudflare.com', '/cdn-cgi/trace').then(parseCfCdnCgiTrace); return this.get('speed.cloudflare.com', '/cdn-cgi/trace').then(parseCfCdnCgiTrace);
} }

View File

@ -1,6 +1,7 @@
import * as plugins from './smartnetwork.plugins.js'; import * as plugins from './smartnetwork.plugins.js';
import { CloudflareSpeed } from './smartnetwork.classes.cloudflarespeed.js'; import { CloudflareSpeed } from './smartnetwork.classes.cloudflarespeed.js';
import { getLogger } from './logging.js';
/** /**
* SmartNetwork simplifies actions within the network * SmartNetwork simplifies actions within the network
@ -16,7 +17,10 @@ export class SmartNetwork {
return test; return test;
} }
public async ping(hostArg: string, timeoutArg: number = 500): Promise<ReturnType<typeof plugins.smartping.Smartping.prototype.ping>> { public async ping(
hostArg: string,
timeoutArg: number = 500,
): Promise<ReturnType<typeof plugins.smartping.Smartping.prototype.ping>> {
const smartpingInstance = new plugins.smartping.Smartping(); const smartpingInstance = new plugins.smartping.Smartping();
const pingResult = await smartpingInstance.ping(hostArg, timeoutArg); const pingResult = await smartpingInstance.ping(hostArg, timeoutArg);
return pingResult; return pingResult;
@ -34,11 +38,7 @@ export class SmartNetwork {
// test IPv4 space // test IPv4 space
const ipv4Test = net.createServer(); const ipv4Test = net.createServer();
ipv4Test.once('error', (err: any) => { ipv4Test.once('error', () => {
if (err.code !== 'EADDRINUSE') {
doneIpV4.resolve(false);
return;
}
doneIpV4.resolve(false); doneIpV4.resolve(false);
}); });
ipv4Test.once('listening', () => { ipv4Test.once('listening', () => {
@ -53,11 +53,7 @@ export class SmartNetwork {
// test IPv6 space // test IPv6 space
const ipv6Test = net.createServer(); const ipv6Test = net.createServer();
ipv6Test.once('error', function (err: any) { ipv6Test.once('error', () => {
if (err.code !== 'EADDRINUSE') {
doneIpV6.resolve(false);
return;
}
doneIpV6.resolve(false); doneIpV6.resolve(false);
}); });
ipv6Test.once('listening', () => { ipv6Test.once('listening', () => {
@ -84,14 +80,15 @@ export class SmartNetwork {
const domainPart = domainArg.split(':')[0]; const domainPart = domainArg.split(':')[0];
const port = portArg ? portArg : parseInt(domainArg.split(':')[1], 10); const port = portArg ? portArg : parseInt(domainArg.split(':')[1], 10);
plugins.isopen(domainPart, port, (response: any) => { plugins.isopen(
console.log(response); domainPart,
if (response[port.toString()].isOpen) { port,
done.resolve(true); (response: Record<string, { isOpen: boolean }>) => {
} else { getLogger().debug(response);
done.resolve(false); const portInfo = response[port.toString()];
} done.resolve(Boolean(portInfo?.isOpen));
}); },
);
const result = await done.promise; const result = await done.promise;
return result; return result;
} }
@ -107,7 +104,7 @@ export class SmartNetwork {
}> { }> {
const defaultGatewayName = await plugins.systeminformation.networkInterfaceDefault(); const defaultGatewayName = await plugins.systeminformation.networkInterfaceDefault();
if (!defaultGatewayName) { if (!defaultGatewayName) {
console.log('Cannot determine default gateway'); getLogger().warn?.('Cannot determine default gateway');
return null; return null;
} }
const gateways = await this.getGateways(); const gateways = await this.getGateways();
@ -120,18 +117,22 @@ export class SmartNetwork {
public async getPublicIps() { public async getPublicIps() {
return { return {
v4: await plugins.publicIp.publicIpv4({ v4: await plugins.publicIp
timeout: 1000, .publicIpv4({
onlyHttps: true, timeout: 1000,
}).catch(async (err) => { onlyHttps: true,
return null })
}), .catch(async (err) => {
v6: await plugins.publicIp.publicIpv6({ return null;
timeout: 1000, }),
onlyHttps: true, v6: await plugins.publicIp
}).catch(async (err) => { .publicIpv6({
return null timeout: 1000,
}) onlyHttps: true,
})
.catch(async (err) => {
return null;
}),
}; };
} }
} }

View File

@ -6,9 +6,11 @@
"module": "NodeNext", "module": "NodeNext",
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
"esModuleInterop": true, "esModuleInterop": true,
"verbatimModuleSyntax": true "verbatimModuleSyntax": true,
"baseUrl": ".",
"paths": {}
}, },
"exclude": [ "exclude": [
"dist_*/**/*.d.ts" "dist_*/**/*.d.ts"
] ]
} }