Compare commits

...

84 Commits

Author SHA1 Message Date
d6be2e27b0 3.0.5 2025-04-28 15:30:08 +00:00
d6c0af35fa fix(core): Improve logging and error handling by introducing custom error classes and a global logging interface while refactoring network diagnostics methods. 2025-04-28 15:30:08 +00:00
bc19c21949 3.0.4 2025-04-28 12:58:01 +00:00
dba1855eb6 fix(ci/config): Improve CI workflows, update project configuration, and clean up code formatting 2025-04-28 12:58:01 +00:00
db01586eb9 3.0.3 2025-04-28 12:04:08 +00:00
172fce2466 fix(deps): Update dependency namespaces and bump package versions in CI configuration and source imports 2025-04-28 12:04:08 +00:00
f7f009e0d4 update description 2024-05-29 14:14:57 +02:00
e5111f0433 update tsconfig 2024-04-14 18:02:08 +02:00
554a7d9647 update npmextra.json: githost 2024-04-01 21:36:49 +02:00
76d30b7618 update npmextra.json: githost 2024-04-01 19:59:04 +02:00
eee90810da update npmextra.json: githost 2024-03-30 21:48:03 +01:00
5bf7d19bf7 switch to new org scheme 2023-07-11 01:15:20 +02:00
2fa6da38c6 switch to new org scheme 2023-07-10 10:16:49 +02:00
e11157fe44 3.0.2 2022-10-22 17:39:29 +02:00
28d99ecb77 fix(core): update 2022-10-22 17:39:29 +02:00
d8f409c191 3.0.1 2022-10-21 17:13:06 +02:00
bcfa3be58b fix(core): update 2022-10-21 17:13:06 +02:00
15744d3c4e 3.0.0 2022-03-24 23:11:53 +01:00
8b2f541150 BREAKING CHANGE(core): switch to esm 2022-03-24 23:11:53 +01:00
b52bb4b474 2.0.14 2022-02-17 00:33:12 +01:00
42f5d66fc4 fix(core): update 2022-02-17 00:33:11 +01:00
54bb9549a1 2.0.13 2022-02-17 00:18:23 +01:00
95c3314400 fix(core): update 2022-02-17 00:18:23 +01:00
695d047200 2.0.12 2022-02-17 00:03:13 +01:00
c308589d28 fix(core): update 2022-02-17 00:03:13 +01:00
068177b09d 2.0.11 2022-02-16 23:28:12 +01:00
4a299cf3cb fix(core): update 2022-02-16 23:28:12 +01:00
e5c37b1801 2.0.10 2021-04-29 15:12:05 +00:00
5be0586790 fix(core): update 2021-04-29 15:12:05 +00:00
f5e5297d47 2.0.9 2021-04-28 14:32:56 +00:00
718fada493 fix(core): update 2021-04-28 14:32:56 +00:00
a42b1b48b5 2.0.8 2021-04-28 14:31:31 +00:00
5ec50975f3 fix(core): update 2021-04-28 14:31:30 +00:00
ad222abb6a 2.0.7 2021-04-28 14:27:23 +00:00
b29e13b162 fix(core): update 2021-04-28 14:27:22 +00:00
9544823401 2.0.6 2021-04-28 13:41:56 +00:00
260f000304 fix(core): update 2021-04-28 13:41:55 +00:00
d8044507ed 2.0.5 2021-04-27 09:46:32 +00:00
b9380be999 fix(core): update 2021-04-27 09:46:31 +00:00
1b9c354d69 2.0.4 2021-04-13 13:05:48 +00:00
a8f4ecf98f fix(core): update 2021-04-13 13:05:47 +00:00
6350088d2a 2.0.3 2021-04-13 10:29:43 +00:00
10ef1d0455 fix(core): update 2021-04-13 10:29:42 +00:00
f709238e50 2.0.2 2021-04-13 10:09:40 +00:00
49940635d5 fix(core): update 2021-04-13 10:09:39 +00:00
ec4121cbcf 2.0.1 2021-04-13 10:09:09 +00:00
ea9a2572f9 fix(core): update 2021-04-13 10:09:09 +00:00
cc0f1c40a6 2.0.0 2021-04-13 10:07:39 +00:00
9da04081e4 BREAKING CHANGE(core): update 2021-04-13 10:07:39 +00:00
4ae0925043 1.1.22 2020-08-13 02:34:06 +00:00
4e862e784b fix(core): update 2020-08-13 02:34:06 +00:00
cf8abfd4f0 1.1.21 2020-08-13 02:29:10 +00:00
93c4488b9b fix(core): update 2020-08-13 02:29:09 +00:00
39493465c6 1.1.20 2020-08-12 16:30:18 +00:00
cab696e45b fix(core): update 2020-08-12 16:30:17 +00:00
67682892ae 1.1.19 2020-08-12 16:29:04 +00:00
5c13987686 fix(core): update 2020-08-12 16:29:03 +00:00
97841e0973 1.1.18 2019-11-23 19:33:49 +00:00
c8ccde9d84 1.1.17 2019-11-23 16:07:05 +00:00
654a4c6b54 fix(core): update 2019-11-23 16:07:04 +00:00
12b8793c19 1.1.16 2019-11-19 23:01:22 +00:00
24e861e5b4 fix(security): add snyk config 2019-11-19 23:01:21 +00:00
c7d2b2c031 1.1.15 2019-11-19 23:00:38 +00:00
f08713bb45 fix(dependencies update): update 2019-11-19 23:00:37 +00:00
ad0fa8c65a 1.1.14 2019-09-08 16:24:59 +02:00
88a9bfc20d fix(core): update 2019-09-08 16:24:59 +02:00
0248d6f253 1.1.13 2019-09-08 16:15:10 +02:00
8d1b302e70 fix(core): update 2019-09-08 16:15:10 +02:00
34bee225d5 1.1.12 2019-09-08 15:52:02 +02:00
ccece078a2 fix(core): update 2019-09-08 15:52:01 +02:00
a04151e537 1.1.11 2019-09-08 15:19:16 +02:00
d71346e763 fix(core): update 2019-09-08 15:19:16 +02:00
817894b6ce 1.1.10 2019-09-08 14:59:47 +02:00
bba219ddef fix(core): update 2019-09-08 14:59:47 +02:00
9af53a5b58 1.1.9 2019-09-06 18:35:04 +02:00
4fcdeb8c3d fix(core): update 2019-09-06 18:35:03 +02:00
5c7d2de902 1.1.8 2019-09-06 18:28:40 +02:00
f105cdc806 fix(core): update 2019-09-06 18:28:39 +02:00
8f71c68d8c 1.1.7 2019-09-06 18:26:32 +02:00
beb6680856 fix(core): update 2019-09-06 18:26:32 +02:00
311852efe8 1.1.6 2019-04-18 00:04:03 +02:00
d3a507c3ff fix(core): update 2019-04-18 00:04:02 +02:00
05bc8fb72c 1.1.5 2019-04-17 20:05:08 +02:00
df861590c8 fix(core): update 2019-04-17 20:05:07 +02:00
28 changed files with 11223 additions and 2170 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

18
.gitignore vendored
View File

@ -1,5 +1,19 @@
.nogit/
node_modules/
# artifacts
coverage/
public/
pages/
# installs
node_modules/
# caches
.yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_*/
#------# custom

View File

@ -1,125 +0,0 @@
# gitzone standard
image: hosttoday/ht-docker-node:npmci
cache:
paths:
- .npmci_cache/
key: "$CI_BUILD_STAGE"
stages:
- security
- test
- release
- metadata
# ====================
# security stage
# ====================
mirror:
stage: security
script:
- npmci git mirror
tags:
- docker
- notpriv
snyk:
stage: security
script:
- npmci npm prepare
- npmci command npm install -g snyk
- npmci command npm install --ignore-scripts
- npmci command snyk test
tags:
- docker
- notpriv
# ====================
# test stage
# ====================
testLTS:
stage: test
script:
- npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
testSTABLE:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
release:
stage: release
script:
- npmci node install stable
- npmci npm publish
only:
- tags
tags:
- docker
- notpriv
# ====================
# metadata stage
# ====================
codequality:
stage: metadata
image: docker:stable
allow_failure: true
services:
- docker:stable-dind
script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
tags:
- docker
- priv
trigger:
stage: metadata
script:
- npmci trigger
only:
- tags
tags:
- docker
- notpriv
pages:
image: hosttoday/ht-docker-node:npmci
stage: metadata
script:
- npmci command npm install -g typedoc typescript
- npmci npm prepare
- npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/
tags:
- docker
- notpriv
only:
- tags
artifacts:
expire_in: 1 week
paths:
- public
allow_failure: true

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "npm test",
"name": "Run npm test",
"request": "launch",
"type": "node-terminal"
}
]
}

26
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"schema": {
"type": "object",
"properties": {
"npmci": {
"type": "object",
"description": "settings for npmci"
},
"gitzone": {
"type": "object",
"description": "settings for gitzone",
"properties": {
"projectType": {
"type": "string",
"enum": ["website", "element", "service", "npm", "wcc"]
}
}
}
}
}
}
]
}

201
changelog.md Normal file
View File

@ -0,0 +1,201 @@
# 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)
Update dependency namespaces and bump package versions in CI configuration and source imports
- Renamed dependency imports from '@pushrocks/...' to '@push.rocks/...' in package.json, test files, and source files
- Updated devDependencies versions and package references (e.g., tsbuild, tsrun, tstest, smartenv, tapbundle, smartpromise, smartstring, public-ip, and @types packages)
- Fixed CI command to install '@git.zone/tsdoc' instead of the misspelled '@gitzone/tsdoc'
- Updated commit info file to reflect the correct package namespace
## 2024-05-29 - 3.0.2 - misc
Various documentation, configuration, and organizational updates.
- Updated project description.
- Updated tsconfig configuration.
- Updated npmextra.json (githost configuration) across multiple commits.
- Switched to a new organizational scheme.
## 2022-10-22 - 3.0.1 - core
Core fixes and maintenance applied.
- Fixed core issues.
## 2022-10-21 - 3.0.0 - core
Core updates and fixes.
- Fixed core issues.
## 2022-03-24 - 2.0.14 - core
Breaking changes introduced.
- BREAKING CHANGE: Switched core to an ECMAScript Modules (ESM) approach.
## 2022-02-16 - 2.0.13 - core
Core maintenance update.
- Fixed core issues.
## 2022-02-16 - 2.0.12 - core
Core maintenance update.
- Fixed core issues.
## 2022-02-16 - 2.0.11 - core
Core maintenance update.
- Fixed core issues.
## 2022-02-16 - 2.0.10 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-29 - 2.0.9 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-28 - 2.0.8 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-28 - 2.0.7 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-28 - 2.0.6 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-28 - 2.0.5 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-27 - 2.0.4 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-13 - 2.0.3 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-13 - 2.0.2 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-13 - 2.0.1 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-13 - 2.0.0 - core
Core maintenance update.
- Fixed core issues.
## 2021-04-13 - 1.1.22 - core
Breaking update in core functionality.
- BREAKING CHANGE: Updated core functionality.
## 2020-08-13 - 1.1.21 - core
Core maintenance update.
- Fixed core issues.
## 2020-08-13 - 1.1.20 - core
Core maintenance update.
- Fixed core issues.
## 2020-08-12 - 1.1.19 - core
Core maintenance update.
- Fixed core issues.
## 2020-08-12 - 1.1.18 - core
Core maintenance update.
- Fixed core issues.
## 2019-11-23 - 1.1.17 - minor
Release with no notable changes.
- No significant changes.
## 2019-11-23 - 1.1.16 - core
Core maintenance update.
- Fixed core issues.
## 2019-11-19 - 1.1.15 - security
Security enhancement.
- Added Snyk configuration for improved security.
## 2019-11-19 - 1.1.14 - dependencies
Dependency update.
- Updated dependencies.
## 2019-09-08 - 1.1.13 - core
Core maintenance update.
- Fixed core issues.
## 2019-09-08 - 1.1.12 - core
Core maintenance update.
- Fixed core issues.
## 2019-09-08 - 1.1.11 - core
Core maintenance update.
- Fixed core issues.
## 2019-09-08 - 1.1.10 - core
Core maintenance update.
- Fixed core issues.
## 2019-09-08 - 1.1.9 - core
Core maintenance update.
- Fixed core issues.
## 2019-09-06 - 1.1.8 - core
Core maintenance update.
- Fixed core issues.
## 2019-09-06 - 1.1.7 - core
Core maintenance update.
- Fixed core issues.
## 2019-09-06 - 1.1.6 - core
Core maintenance update.
- Fixed core issues.
## 2019-04-17 - 1.1.5 - core
Core maintenance update.
- Fixed core issues.
## 2019-04-17 - 1.1.4 - core
Core maintenance update.
- Fixed core issues.
## 2019-04-17 - 1.1.3 - core
Core maintenance update.
- Fixed core issues.
## 2019-04-17 - 1.1.2 - core
Core maintenance update.
- Fixed core issues.
## 2019-04-16 - 1.1.1 - core
Core maintenance update.
- Fixed core issues.
## 2019-04-16 - 1.1.0 - core
Core maintenance update.
- Fixed core issues.
## 2018-07-17 - 1.0.2 - feature
New feature added.
- Added port checking functionality.
## 2017-12-12 - 1.0.1 - initial
Initial commit.
- Initial project setup.

23
license Normal file
View File

@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright (c) 2015 Lossless GmbH
Copyright (c) 2020 Tomás Arias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -4,13 +4,29 @@
"npmAccessLevel": "public"
},
"gitzone": {
"projectType": "npm",
"module": {
"githost": "gitlab.com",
"gitscope": "pushrocks",
"githost": "code.foss.global",
"gitscope": "push.rocks",
"gitrepo": "smartnetwork",
"shortDescription": "network diagnostics",
"npmPackagename": "@pushrocks/smartnetwork",
"license": "MIT"
"description": "A toolkit for network diagnostics including speed tests, port availability checks, and more.",
"npmPackagename": "@push.rocks/smartnetwork",
"license": "MIT",
"keywords": [
"network diagnostics",
"ping",
"port check",
"speed test",
"network interface",
"public IP retrieval",
"Cloudflare speed test",
"network performance",
"network utility",
"TypeScript"
]
}
},
"tsdoc": {
"legal": "\n## License and Legal Information\n\nThis 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. \n\n**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.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
}
}

1898
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,72 @@
{
"name": "@pushrocks/smartnetwork",
"version": "1.1.4",
"name": "@push.rocks/smartnetwork",
"version": "3.0.5",
"private": false,
"description": "network diagnostics",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"description": "A toolkit for network diagnostics including speed tests, port availability checks, and more.",
"main": "dist_ts/index.js",
"typings": "dist_ts/index.d.ts",
"type": "module",
"author": "Lossless GmbH",
"license": "MIT",
"scripts": {
"test": "(tsrun test/)",
"build": "(tsbuild)"
"test": "(tstest test/)",
"build": "(tsbuild --web --allowimplicitany)",
"buildDocs": "tsdoc"
},
"devDependencies": {
"@gitzone/tsbuild": "^2.1.8",
"@gitzone/tstest": "^1.0.20",
"@pushrocks/tapbundle": "^3.0.9",
"tslint": "^5.15.0",
"tslint-config-prettier": "^1.18.0"
"@git.zone/tsbuild": "^2.1.61",
"@git.zone/tsrun": "^1.2.39",
"@git.zone/tstest": "^1.0.69",
"@push.rocks/smartenv": "^5.0.0",
"@push.rocks/tapbundle": "^5.0.3",
"@types/node": "^22.15.3"
},
"dependencies": {
"@pushrocks/smartpromise": "^3.0.2",
"@pushrocks/smartstring": "^3.0.10",
"@types/portscanner": "^2.1.0",
"portscanner": "^2.2.0",
"speedtest-net": "^1.5.1"
"@push.rocks/smartping": "^1.0.7",
"@push.rocks/smartpromise": "^4.2.3",
"@push.rocks/smartstring": "^4.0.2",
"@types/default-gateway": "^7.2.2",
"isopen": "^1.3.0",
"public-ip": "^7.0.1",
"systeminformation": "^5.11.9"
},
"files": [
"ts/**/*",
"ts_web/**/*",
"dist/**/*",
"dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
],
"browserslist": [
"last 1 chrome versions"
],
"keywords": [
"network diagnostics",
"ping",
"port check",
"speed test",
"network interface",
"public IP retrieval",
"Cloudflare speed test",
"network performance",
"network utility",
"TypeScript"
],
"homepage": "https://code.foss.global/push.rocks/smartnetwork#readme",
"repository": {
"type": "git",
"url": "https://code.foss.global/push.rocks/smartnetwork.git"
},
"packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6",
"bugs": {
"url": "https://code.foss.global/push.rocks/smartnetwork/issues"
},
"pnpm": {
"overrides": {}
}
}

9958
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

1
readme.hints.md Normal file
View File

@ -0,0 +1 @@

160
readme.md
View File

@ -1,32 +1,150 @@
# @pushrocks/smartnetwork
# @push.rocks/smartnetwork
network diagnostics
## Availabililty and Links
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartnetwork)
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartnetwork)
* [github.com (source mirror)](https://github.com/pushrocks/smartnetwork)
* [docs (typedoc)](https://pushrocks.gitlab.io/smartnetwork/)
## Install
## Status for master
[![build status](https://gitlab.com/pushrocks/smartnetwork/badges/master/build.svg)](https://gitlab.com/pushrocks/smartnetwork/commits/master)
[![coverage report](https://gitlab.com/pushrocks/smartnetwork/badges/master/coverage.svg)](https://gitlab.com/pushrocks/smartnetwork/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/@pushrocks/smartnetwork.svg)](https://www.npmjs.com/package/@pushrocks/smartnetwork)
[![Known Vulnerabilities](https://snyk.io/test/npm/@pushrocks/smartnetwork/badge.svg)](https://snyk.io/test/npm/@pushrocks/smartnetwork)
[![TypeScript](https://img.shields.io/badge/TypeScript->=%203.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-prettier-ff69b4.svg)](https://prettier.io/)
To install `@push.rocks/smartnetwork`, run the following command in your terminal:
```bash
npm install @push.rocks/smartnetwork --save
```
This command will download `@push.rocks/smartnetwork` and add it to your project's `package.json` file.
## Usage
In this section, we will dive deep into the capabilities of the `@push.rocks/smartnetwork` package, exploring its various features through TypeScript examples. The package is designed to simplify network diagnostics tasks, including speed tests, port availability checks, ping operations, and more.
### Basic Setup
First, import the package into your project:
```typescript
import * as smartnetwork from 'smartnetwork';
testSmartNetwork = new smartnetwork.SmartNetwork();
testSmartNetwork.getSpeed
import { SmartNetwork } from '@push.rocks/smartnetwork';
```
For further information read the linked docs at the top of this readme.
Then, create an instance of `SmartNetwork`:
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
```typescript
const myNetwork = new SmartNetwork();
```
[![repo-footer](https://pushrocks.gitlab.io/assets/repo-footer.svg)](https://maintainedby.lossless.com)
### Performing a Speed Test
You can measure the network speed using the `getSpeed` method. This feature leverages Cloudflare's speed test capabilities to assess your internet connection's download and upload speeds.
```typescript
const speedTest = async () => {
const speedResult = await myNetwork.getSpeed();
console.log(`Download speed: ${speedResult.downloadSpeed} Mbps`);
console.log(`Upload speed: ${speedResult.uploadSpeed} Mbps`);
console.log(`Latency: ${speedResult.averageTime} ms`);
};
speedTest();
```
### Checking Port Availability Locally
The `isLocalPortUnused` method allows you to check if a specific port on your local machine is available for use.
```typescript
const checkLocalPort = async (port: number) => {
const isUnused = await myNetwork.isLocalPortUnused(port);
if (isUnused) {
console.log(`Port ${port} is available.`);
} else {
console.log(`Port ${port} is in use.`);
}
};
checkLocalPort(8080); // Example port number
```
### Checking Remote Port Availability
To verify if a certain port is available on a remote server, use `isRemotePortAvailable`. This can help determine if a service is up and reachable.
```typescript
const checkRemotePort = async (hostname: string, port: number) => {
const isAvailable = await myNetwork.isRemotePortAvailable(hostname, port);
if (isAvailable) {
console.log(`Port ${port} on ${hostname} is available.`);
} else {
console.log(`Port ${port} on ${hostname} is not available.`);
}
};
checkRemotePort('example.com', 443); // Checking HTTPS port on example.com
```
### Using Ping
The `ping` method allows you to send ICMP packets to a host to measure round-trip time and determine if the host is reachable.
```typescript
const pingHost = async (hostname: string) => {
const pingResult = await myNetwork.ping(hostname);
if (pingResult.alive) {
console.log(`${hostname} is reachable. RTT: ${pingResult.time} ms`);
} else {
console.log(`${hostname} is not reachable.`);
}
};
pingHost('google.com');
```
### Getting Network Gateways
You can also retrieve information about your network gateways, including the default gateway used by your machine.
```typescript
const showGateways = async () => {
const gateways = await myNetwork.getGateways();
console.log(gateways);
const defaultGateway = await myNetwork.getDefaultGateway();
console.log(`Default Gateway: `, defaultGateway);
};
showGateways();
```
### Discovering Public IP Addresses
To find out your public IPv4 and IPv6 addresses, the following method can be used:
```typescript
const showPublicIps = async () => {
const publicIps = await myNetwork.getPublicIps();
console.log(`Public IPv4: ${publicIps.v4}`);
console.log(`Public IPv6: ${publicIps.v6}`);
};
showPublicIps();
```
The `@push.rocks/smartnetwork` package provides an easy-to-use, comprehensive suite of tools for network diagnostics and monitoring, encapsulating complex network operations into simple asynchronous methods. By leveraging TypeScript, developers can benefit from type checking, ensuring that they can work with clear structures and expectations.
These examples offer a glimpse into the module's utility in real-world scenarios, demonstrating its versatility in handling common network tasks. Whether you're developing a network-sensitive application, diagnosing connectivity issues, or simply curious about your network performance, `@push.rocks/smartnetwork` equips you with the tools you need.
## 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.
**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.
### Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
### Company Information
Task Venture Capital GmbH
Registered at District court Bremen HRB 35230 HB, Germany
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

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.

25
test/test.ping.ts Normal file
View File

@ -0,0 +1,25 @@
import { tap, expect, expectAsync } from '@push.rocks/tapbundle';
import * as smartnetwork from '../ts/index.js';
let testSmartnetwork: smartnetwork.SmartNetwork;
tap.test('should create a vlid instance of SmartNetwork', async () => {
testSmartnetwork = new smartnetwork.SmartNetwork();
expect(testSmartnetwork).toBeInstanceOf(smartnetwork.SmartNetwork);
});
tap.test('should send a ping to Google', async () => {
console.log(await testSmartnetwork.ping('google.com'));
await expectAsync(testSmartnetwork.ping('google.com')).property('alive').toBeTrue();
});
tap.test('should state when a ping is not alive ', async () => {
await expectAsync(testSmartnetwork.ping('notthere.lossless.com')).property('alive').toBeFalse();
});
tap.test('should send a ping to an IP', async () => {
await expectAsync(testSmartnetwork.ping('192.168.186.999')).property('alive').toBeFalse();
});
tap.start();

View File

@ -1,26 +1,42 @@
import { expect, tap } from '@pushrocks/tapbundle';
import * as smartnetwork from '../ts/index';
import { expect, expectAsync, tap } from '@push.rocks/tapbundle';
import * as smartnetwork from '../ts/index.js';
let testSmartNetwork: smartnetwork.SmartNetwork;
tap.test('should create a valid instance of SmartNetwork', async () => {
testSmartNetwork = new smartnetwork.SmartNetwork();
expect(testSmartNetwork).to.be.instanceOf(smartnetwork.SmartNetwork);
expect(testSmartNetwork).toBeInstanceOf(smartnetwork.SmartNetwork);
});
tap.test('should perform a speedtest', async () => {
let result = await testSmartNetwork.getSpeed();
console.log(`Download speed for this instance is ${result.speeds.download}`);
console.log(`Upload speed for this instance is ${result.speeds.upload}`);
const result = await testSmartNetwork.getSpeed();
console.log(`Download speed for this instance is ${result.downloadSpeed}`);
console.log(`Upload speed for this instance is ${result.uploadSpeed}`);
});
tap.test('should determine wether a port is free', async () => {
await expect(testSmartNetwork.isLocalPortAvailable(8080)).to.eventually.be.true;
await expectAsync(testSmartNetwork.isLocalPortUnused(8080)).toBeTrue();
});
tap.test('should scan a port', async () => {
await expect(testSmartNetwork.isRemotePortAvailable('google.com:80')).to.eventually.be.true;
await expect(testSmartNetwork.isRemotePortAvailable('67.207.79.63:12346')).to.eventually.be.false;
await expectAsync(testSmartNetwork.isRemotePortAvailable('lossless.com:443')).toBeTrue();
await expectAsync(testSmartNetwork.isRemotePortAvailable('lossless.com', 443)).toBeTrue();
await expectAsync(testSmartNetwork.isRemotePortAvailable('lossless.com:444')).toBeFalse();
});
tap.test('should get gateways', async () => {
const gatewayResult = await testSmartNetwork.getGateways();
console.log(gatewayResult);
});
tap.test('should get the default gateway', async () => {
const gatewayResult = await testSmartNetwork.getDefaultGateway();
console.log(gatewayResult);
});
tap.test('should get public ips', async () => {
const ips = await testSmartNetwork.getPublicIps();
console.log(ips);
});
tap.start();

8
ts/00_commitinfo_data.ts Normal file
View File

@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @push.rocks/commitinfo
*/
export const commitinfo = {
name: '@push.rocks/smartnetwork',
version: '3.0.5',
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);
}
}

43
ts/helpers/stats.ts Normal file
View File

@ -0,0 +1,43 @@
export function average(values: number[]) {
let total = 0;
for (let i = 0; i < values.length; i += 1) {
total += values[i];
}
return total / values.length;
}
export function median(values: number[]) {
const half = Math.floor(values.length / 2);
values.sort((a, b) => a - b);
if (values.length % 2) return values[half];
return (values[half - 1] + values[half]) / 2;
}
export function quartile(values: number[], percentile: number) {
values.sort((a, b) => a - b);
const pos = (values.length - 1) * percentile;
const base = Math.floor(pos);
const rest = pos - base;
if (values[base + 1] !== undefined) {
return values[base] + rest * (values[base + 1] - values[base]);
}
return values[base];
}
export function jitter(values: number[]) {
// Average distance between consecutive latency measurements...
let jitters = [];
for (let i = 0; i < values.length - 1; i += 1) {
jitters.push(Math.abs(values[i] - values[i + 1]));
}
return average(jitters);
}

View File

@ -1 +1 @@
export * from './smartnetwork.classes.smartnetwork';
export * from './smartnetwork.classes.smartnetwork.js';

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

@ -0,0 +1,260 @@
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';
export class CloudflareSpeed {
constructor() {}
public async speedTest() {
const latency = await this.measureLatency();
const serverLocations = await this.fetchServerLocations();
const cgiData = await this.fetchCfCdnCgiTrace();
// lets test the download speed
const testDown1 = await this.measureDownload(101000, 10);
const testDown2 = await this.measureDownload(1001000, 8);
const testDown3 = await this.measureDownload(10001000, 6);
const testDown4 = await this.measureDownload(25001000, 4);
const testDown5 = await this.measureDownload(100001000, 1);
const downloadTests = [...testDown1, ...testDown2, ...testDown3, ...testDown4, ...testDown5];
const speedDownload = stats.quartile(downloadTests, 0.9).toFixed(2);
// lets test the upload speed
const testUp1 = await this.measureUpload(11000, 10);
const testUp2 = await this.measureUpload(101000, 10);
const testUp3 = await this.measureUpload(1001000, 8);
const uploadTests = [...testUp1, ...testUp2, ...testUp3];
const speedUpload = stats.quartile(uploadTests, 0.9).toFixed(2);
return {
...latency,
ip: cgiData.ip,
serverLocation: {
shortId: cgiData.colo,
name: serverLocations[cgiData.colo],
availableLocations: serverLocations,
},
downloadSpeed: speedDownload,
uploadSpeed: speedUpload,
};
}
public async measureLatency() {
const measurements: number[] = [];
for (let i = 0; i < 20; i += 1) {
await this.download(1000).then(
(response) => {
// TTFB - Server processing time
measurements.push(response[4] - response[0] - response[6]);
},
(error) => {
getLogger().error('Error measuring latency:', error);
},
);
}
return {
maxTime: Math.max(...measurements),
minTime: Math.min(...measurements),
averageTime: stats.average(measurements),
medianTime: stats.median(measurements),
jitter: stats.jitter(measurements),
};
}
public async measureDownload(bytes: number, iterations: number) {
const measurements: number[] = [];
for (let i = 0; i < iterations; i += 1) {
await this.download(bytes).then(
async (response) => {
const transferTime = response[5] - response[4];
measurements.push(await this.measureSpeed(bytes, transferTime));
},
(error) => {
getLogger().error('Error measuring download chunk:', error);
},
);
}
return measurements;
}
public async measureUpload(bytes: number, iterations: number) {
const measurements: number[] = [];
for (let i = 0; i < iterations; i += 1) {
await this.upload(bytes).then(
async (response) => {
const transferTime = response[6];
measurements.push(await this.measureSpeed(bytes, transferTime));
},
(error) => {
getLogger().error('Error measuring upload chunk:', error);
},
);
}
return measurements;
}
public async measureSpeed(bytes: number, duration: number) {
return (bytes * 8) / (duration / 1000) / 1e6;
}
public async fetchServerLocations(): Promise<{ [key: string]: string }> {
const res = JSON.parse(
await this.get('speed.cloudflare.com', '/locations'),
) as Array<{ iata: string; city: string }>;
return res.reduce(
(data: Record<string, string>, optionsArg) => {
data[optionsArg.iata] = optionsArg.city;
return data;
},
{} as Record<string, string>,
);
}
public async get(hostname: string, path: string): Promise<string> {
return new Promise((resolve, reject) => {
const req = plugins.https.request(
{
hostname,
path,
method: 'GET',
// disable connection pooling to avoid listener accumulation
agent: false,
},
(res) => {
const body: Array<Buffer> = [];
res.on('data', (chunk) => {
body.push(chunk);
});
res.on('end', () => {
try {
resolve(Buffer.concat(body).toString());
} catch (e) {
reject(e);
}
});
req.on('error', (err: Error & { code?: string }) => {
reject(new NetworkError(err.message, err.code));
});
},
);
req.end();
});
}
public async download(bytes: number) {
const options = {
hostname: 'speed.cloudflare.com',
path: `/__down?bytes=${bytes}`,
method: 'GET',
};
return this.request(options);
}
public async upload(bytes: number) {
const data = '0'.repeat(bytes);
const options = {
hostname: 'speed.cloudflare.com',
path: '/__up',
method: 'POST',
headers: {
'Content-Length': Buffer.byteLength(data),
},
};
return this.request(options, data);
}
public async request(options: plugins.https.RequestOptions, data = ''): Promise<number[]> {
let started: number;
let dnsLookup: number;
let tcpHandshake: number;
let sslHandshake: number;
let ttfb: number;
let ended: number;
return new Promise((resolve, reject) => {
started = plugins.perfHooks.performance.now();
// disable connection pooling to avoid listener accumulation across requests
const reqOptions = { ...options, agent: false };
const req = plugins.https.request(reqOptions, (res) => {
res.once('readable', () => {
ttfb = plugins.perfHooks.performance.now();
});
res.on('data', () => {});
res.on('end', () => {
ended = plugins.perfHooks.performance.now();
resolve([
started,
dnsLookup,
tcpHandshake,
sslHandshake,
ttfb,
ended,
parseFloat((res.headers['server-timing'] as string).slice(22)),
]);
});
});
// Listen for timing events once per new socket
req.once('socket', (socket) => {
socket.once('lookup', () => {
dnsLookup = plugins.perfHooks.performance.now();
});
socket.once('connect', () => {
tcpHandshake = plugins.perfHooks.performance.now();
});
socket.once('secureConnect', () => {
sslHandshake = plugins.perfHooks.performance.now();
});
});
req.on('error', (error) => {
reject(error);
});
req.write(data);
req.end();
});
}
public async fetchCfCdnCgiTrace(): Promise<{
fl: string;
h: string;
ip: string;
ts: string;
visit_scheme: string;
uag: string;
colo: string;
http: string;
loc: string;
tls: string;
sni: string;
warp: string;
gateway: string;
}> {
const parseCfCdnCgiTrace = (text: string) =>
text
.split('\n')
.map((i) => {
const parts = i.split('=');
return [parts[0], parts[1]];
})
.reduce((data: Record<string, string>, [k, v]) => {
if (v === undefined) return data;
data[k] = v;
return data;
}, {} as Record<string, string>);
return this.get('speed.cloudflare.com', '/cdn-cgi/trace').then(parseCfCdnCgiTrace);
}
}

View File

@ -1,51 +1,29 @@
import * as plugins from './smartnetwork.plugins';
import * as plugins from './smartnetwork.plugins.js';
export class ISpeedtestData {
speeds: {
download: number;
upload: number;
originalDownload: number;
originalUpload: number;
};
client: {
ip: string;
lat: number;
lon: number;
isp: string;
isprating: string;
rating: number;
ispdlavg: number;
ispulavg: number;
};
server: {
host: string;
lat: number;
lon: number;
location: string;
country: string;
cc: string;
sponsor: string;
distance: number;
distanceMi: number;
ping: number;
id: string;
};
}
import { CloudflareSpeed } from './smartnetwork.classes.cloudflarespeed.js';
import { getLogger } from './logging.js';
/**
* SmartNetwork simplifies actions within the network
*/
export class SmartNetwork {
async getSpeed(measurementTime = 5000): Promise<ISpeedtestData> {
let done = plugins.smartpromise.defer<ISpeedtestData>();
const test = plugins.speedtestNet({ maxTime: measurementTime });
test.on('data', data => {
done.resolve(data);
});
test.on('error', err => {
done.reject(err);
});
return await done.promise;
/**
* get network speed
* @param measurementTime
*/
public async getSpeed() {
const cloudflareSpeedInstance = new CloudflareSpeed();
const test = await cloudflareSpeedInstance.speedTest();
return test;
}
public async ping(
hostArg: string,
timeoutArg: number = 500,
): Promise<ReturnType<typeof plugins.smartping.Smartping.prototype.ping>> {
const smartpingInstance = new plugins.smartping.Smartping();
const pingResult = await smartpingInstance.ping(hostArg, timeoutArg);
return pingResult;
}
/**
@ -53,21 +31,17 @@ export class SmartNetwork {
* note: false also resolves with false as argument
* @param port
*/
async isLocalPortAvailable(port: number): Promise<boolean> {
public async isLocalPortUnused(port: number): Promise<boolean> {
const doneIpV4 = plugins.smartpromise.defer<boolean>();
const doneIpV6 = plugins.smartpromise.defer<boolean>();
const net = await import('net'); // creates only one instance of net ;) even on multiple calls
// test IPv4 space
const ipv4Test = net.createServer();
ipv4Test.once('error', function(err: any) {
if (err.code !== 'EADDRINUSE') {
doneIpV4.resolve(false);
return;
}
ipv4Test.once('error', () => {
doneIpV4.resolve(false);
});
ipv4Test.once('listening', function() {
ipv4Test.once('listening', () => {
ipv4Test.once('close', () => {
doneIpV4.resolve(true);
});
@ -78,21 +52,17 @@ export class SmartNetwork {
await doneIpV4.promise;
// test IPv6 space
const test_ipv6 = net.createServer();
test_ipv6.once('error', function(err: any) {
if (err.code !== 'EADDRINUSE') {
doneIpV6.resolve(false);
return;
}
const ipv6Test = net.createServer();
ipv6Test.once('error', () => {
doneIpV6.resolve(false);
});
test_ipv6.once('listening', function() {
test_ipv6.once('close', () => {
ipv6Test.once('listening', () => {
ipv6Test.once('close', () => {
doneIpV6.resolve(true);
});
test_ipv6.close();
ipv6Test.close();
});
test_ipv6.listen(port, '::');
ipv6Test.listen(port, '::');
// lets wait for the result
const resultIpV4 = await doneIpV4.promise;
@ -110,17 +80,59 @@ export class SmartNetwork {
const domainPart = domainArg.split(':')[0];
const port = portArg ? portArg : parseInt(domainArg.split(':')[1], 10);
plugins.portscanner.checkPortStatus(port, domainPart, (err, status ) => {
if (err) {
throw err;
}
if (status === 'open') {
done.resolve(true);
} else {
done.resolve(false)
}
})
plugins.isopen(
domainPart,
port,
(response: Record<string, { isOpen: boolean }>) => {
getLogger().debug(response);
const portInfo = response[port.toString()];
done.resolve(Boolean(portInfo?.isOpen));
},
);
const result = await done.promise;
return result;
}
public async getGateways() {
const result = plugins.os.networkInterfaces();
return result;
}
public async getDefaultGateway(): Promise<{
ipv4: plugins.os.NetworkInterfaceInfo;
ipv6: plugins.os.NetworkInterfaceInfo;
}> {
const defaultGatewayName = await plugins.systeminformation.networkInterfaceDefault();
if (!defaultGatewayName) {
getLogger().warn?.('Cannot determine default gateway');
return null;
}
const gateways = await this.getGateways();
const defaultGateway = gateways[defaultGatewayName];
return {
ipv4: defaultGateway[0],
ipv6: defaultGateway[1],
};
}
public async getPublicIps() {
return {
v4: await plugins.publicIp
.publicIpv4({
timeout: 1000,
onlyHttps: true,
})
.catch(async (err) => {
return null;
}),
v6: await plugins.publicIp
.publicIpv6({
timeout: 1000,
onlyHttps: true,
})
.catch(async (err) => {
return null;
}),
};
}
}

View File

@ -1,13 +1,22 @@
// native scope
import * as os from 'os';
import * as https from 'https';
import * as perfHooks from 'perf_hooks';
export { os, https, perfHooks };
// @pushrocks scope
import * as smartpromise from '@pushrocks/smartpromise';
import * as smartstring from '@pushrocks/smartstring';
import * as smartping from '@push.rocks/smartping';
import * as smartpromise from '@push.rocks/smartpromise';
import * as smartstring from '@push.rocks/smartstring';
export { smartpromise, smartstring };
export { smartpromise, smartping, smartstring };
// @third party scope
let speedtestNet = require('speedtest-net');
import * as portscanner from 'portscanner';
// @ts-ignore
import isopen from 'isopen';
// @ts-ignore
import * as publicIp from 'public-ip';
import * as systeminformation from 'systeminformation';
export { speedtestNet, portscanner };
export { isopen, publicIp, systeminformation };

5
ts/tsconfig.json Normal file
View File

@ -0,0 +1,5 @@
{
"compilerOptions": {
"noImplicitAny": true
}
}

16
tsconfig.json Normal file
View File

@ -0,0 +1,16 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"verbatimModuleSyntax": true,
"baseUrl": ".",
"paths": {}
},
"exclude": [
"dist_*/**/*.d.ts"
]
}

View File

@ -1,17 +0,0 @@
{
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
}