unping 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Funish
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,409 @@
1
+ # UnPing
2
+
3
+ ![npm version](https://img.shields.io/npm/v/unping)
4
+ ![npm downloads](https://img.shields.io/npm/dw/unping)
5
+ ![npm license](https://img.shields.io/npm/l/unping)
6
+ [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://www.contributor-covenant.org/version/2/1/code_of_conduct/)
7
+
8
+ > Unified network connectivity detection library with multi-driver support
9
+
10
+ ## Features
11
+
12
+ - 🌐 **Multi-Driver Support**: HTTP, TCP, DNS, and Hybrid drivers for different scenarios
13
+ - 🔄 **Driver Pattern**: Consistent API design across different detection methods
14
+ - 📝 **TypeScript First**: Full type safety with comprehensive ping result types
15
+ - 🚀 **High Performance**: Built on modern networking APIs with minimal dependencies
16
+ - ⚡ **Smart Fallback**: Hybrid driver automatically tries multiple detection methods
17
+ - 🔧 **Flexible Configuration**: Support for batch pings, timeouts, intervals, and custom ports
18
+ - 📊 **Rich Results**: Detailed response data including timing and sequence numbers
19
+ - 🛡️ **Error Resilient**: Graceful handling of network failures and timeouts
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ # Install with npm
25
+ $ npm install unping
26
+
27
+ # Install with yarn
28
+ $ yarn add unping
29
+
30
+ # Install with pnpm
31
+ $ pnpm add unping
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Basic Setup
37
+
38
+ ```typescript
39
+ import { createPingManager } from "unping";
40
+ import tcpDriver from "unping/drivers/tcp";
41
+
42
+ // Create ping manager with TCP driver
43
+ const ping = createPingManager({
44
+ driver: tcpDriver({ port: 80 }),
45
+ });
46
+
47
+ // Ping a host
48
+ const results = await ping.ping("google.com");
49
+ console.log(results[0]);
50
+ // { host: "google.com", alive: true, time: 5, sequence: 1 }
51
+ ```
52
+
53
+ ### HTTP Driver
54
+
55
+ Application layer health checks using HTTP HEAD/GET requests.
56
+
57
+ ```typescript
58
+ import httpDriver from "unping/drivers/http";
59
+
60
+ const http = createPingManager({
61
+ driver: httpDriver({ method: "HEAD" }),
62
+ });
63
+
64
+ const results = await http.ping("example.com");
65
+ console.log(`HTTP Status: ${results[0].alive ? "Available" : "Unavailable"}`);
66
+ console.log(`Response Time: ${results[0].time}ms`);
67
+ ```
68
+
69
+ ### TCP Driver
70
+
71
+ Port reachability detection using TCP connections.
72
+
73
+ ```typescript
74
+ import tcpDriver from "unping/drivers/tcp";
75
+
76
+ // Check default HTTP port
77
+ const tcp80 = createPingManager({
78
+ driver: tcpDriver({ port: 80 }),
79
+ });
80
+
81
+ // Check HTTPS port
82
+ const tcp443 = createPingManager({
83
+ driver: tcpDriver({ port: 443 }),
84
+ });
85
+
86
+ const results = await tcp80.ping("example.com");
87
+ console.log(`Port 80: ${results[0].alive ? "Open" : "Closed"}`);
88
+ ```
89
+
90
+ ### DNS Driver
91
+
92
+ DNS resolution capability detection.
93
+
94
+ ```typescript
95
+ import dnsDriver from "unping/drivers/dns";
96
+
97
+ const dns = createPingManager({
98
+ driver: dnsDriver({
99
+ type: "A", // Query A records
100
+ servers: ["8.8.8.8", "1.1.1.1"], // Custom DNS servers
101
+ }),
102
+ });
103
+
104
+ const results = await dns.ping("example.com");
105
+ console.log(`DNS Resolution: ${results[0].alive ? "Success" : "Failed"}`);
106
+ ```
107
+
108
+ ### Hybrid Driver
109
+
110
+ Smart detection with automatic fallback between multiple methods.
111
+
112
+ ```typescript
113
+ import hybridDriver from "unping/drivers/hybrid";
114
+
115
+ const hybrid = createPingManager({
116
+ driver: hybridDriver({
117
+ priority: ["tcp", "http", "dns"], // Try TCP first, then HTTP, then DNS
118
+ }),
119
+ });
120
+
121
+ // Automatically tries TCP → HTTP → DNS until one succeeds
122
+ const results = await hybrid.ping("example.com");
123
+ console.log(`Detection Method: ${results[0].source || "auto"}`);
124
+ console.log(`Alive: ${results[0].alive}`);
125
+ console.log(`Time: ${results[0].time}ms`);
126
+ ```
127
+
128
+ ### Batch Pings
129
+
130
+ Send multiple pings with intervals for detailed analysis.
131
+
132
+ ```typescript
133
+ const results = await ping.ping("example.com", {
134
+ count: 5, // Send 5 pings
135
+ timeout: 3000, // 3 second timeout per ping
136
+ interval: 500, // Wait 500ms between pings
137
+ });
138
+
139
+ results.forEach((result) => {
140
+ console.log(
141
+ `[${result.sequence}] ${result.host}: ${result.alive ? "✓" : "✗"} ${result.time}ms`,
142
+ );
143
+ });
144
+
145
+ // Calculate statistics
146
+ const successRate = results.filter((r) => r.alive).length / results.length;
147
+ const avgTime = results.reduce((sum, r) => sum + r.time, 0) / results.length;
148
+
149
+ console.log(`Success Rate: ${(successRate * 100).toFixed(1)}%`);
150
+ console.log(`Average Time: ${avgTime.toFixed(0)}ms`);
151
+ ```
152
+
153
+ ### Available Drivers
154
+
155
+ ```typescript
156
+ // HTTP driver (application layer)
157
+ import httpDriver from "unping/drivers/http";
158
+
159
+ // TCP driver (port reachability)
160
+ import tcpDriver from "unping/drivers/tcp";
161
+
162
+ // DNS driver (DNS resolution)
163
+ import dnsDriver from "unping/drivers/dns";
164
+
165
+ // Hybrid driver (smart fallback)
166
+ import hybridDriver from "unping/drivers/hybrid";
167
+ ```
168
+
169
+ ### Advanced Configuration
170
+
171
+ #### HTTP Driver Options
172
+
173
+ ```typescript
174
+ import httpDriver from "unping/drivers/http";
175
+
176
+ const http = createPingManager({
177
+ driver: httpDriver({
178
+ method: "GET", // GET or HEAD (default: HEAD)
179
+ port: 8080, // Custom port
180
+ https: true, // Force HTTPS
181
+ path: "/health", // Custom path
182
+ headers: {
183
+ // Custom headers
184
+ "User-Agent": "My-Pinger/1.0",
185
+ },
186
+ }),
187
+ });
188
+ ```
189
+
190
+ #### TCP Driver Options
191
+
192
+ ```typescript
193
+ import tcpDriver from "unping/drivers/tcp";
194
+
195
+ const tcp = createPingManager({
196
+ driver: tcpDriver({
197
+ port: 22, // Custom port
198
+ connectTimeout: 2000, // Connection timeout in ms
199
+ }),
200
+ });
201
+ ```
202
+
203
+ #### DNS Driver Options
204
+
205
+ ```typescript
206
+ import dnsDriver from "unping/drivers/dns";
207
+
208
+ const dns = createPingManager({
209
+ driver: dnsDriver({
210
+ type: "AAAA", // Query AAAA records (IPv6)
211
+ servers: ["8.8.8.8"], // Custom DNS servers
212
+ }),
213
+ });
214
+ ```
215
+
216
+ #### Hybrid Driver Options
217
+
218
+ ```typescript
219
+ import hybridDriver from "unping/drivers/hybrid";
220
+
221
+ const hybrid = createPingManager({
222
+ driver: hybridDriver({
223
+ priority: ["http", "tcp", "dns"], // Custom priority order
224
+ }),
225
+ });
226
+ ```
227
+
228
+ ### Error Handling
229
+
230
+ ```typescript
231
+ try {
232
+ const results = await ping.ping("example.com", { timeout: 5000 });
233
+
234
+ if (results.length > 0) {
235
+ const result = results[0];
236
+
237
+ if (result.alive) {
238
+ console.log(`Host is reachable: ${result.time}ms`);
239
+ } else {
240
+ console.log(`Host is unreachable (timed out)`);
241
+ }
242
+ }
243
+ } catch (error) {
244
+ console.error("Ping failed:", error.message);
245
+ }
246
+ ```
247
+
248
+ ## API Reference
249
+
250
+ ### Ping Manager
251
+
252
+ #### `createPingManager(options)`
253
+
254
+ Creates a new ping manager instance with the specified driver.
255
+
256
+ **Parameters:**
257
+
258
+ - `options.driver` - Ping driver instance (HTTP, TCP, DNS, or Hybrid)
259
+
260
+ **Returns:** Ping manager instance with `ping()` method
261
+
262
+ #### Methods
263
+
264
+ ##### `ping(host, options?)`
265
+
266
+ Ping a host and return results.
267
+
268
+ **Parameters:**
269
+
270
+ - `host` (string) - Hostname or IP address to ping
271
+ - `options` (object, optional) - Ping options
272
+ - `count` (number) - Number of pings to send (default: 1)
273
+ - `timeout` (number) - Timeout in milliseconds per ping (default: 5000)
274
+ - `interval` (number) - Wait time in milliseconds between pings (default: 0)
275
+ - `size` (number) - Packet size in bytes (driver-dependent)
276
+
277
+ **Returns:** `Promise<PingResult[]>` - Array of ping results
278
+
279
+ ### Ping Result
280
+
281
+ ```typescript
282
+ interface PingResult {
283
+ host: string; // Target host
284
+ alive: boolean; // Is reachable
285
+ time: number; // Response time in milliseconds
286
+ sequence?: number; // Sequence number for batch pings
287
+ ttl?: number; // Time to live (when available)
288
+ }
289
+ ```
290
+
291
+ ### Driver Options
292
+
293
+ #### HTTPDriverOptions
294
+
295
+ ```typescript
296
+ interface HTTPDriverOptions {
297
+ method?: "HEAD" | "GET"; // Request method (default: "HEAD")
298
+ port?: number; // Custom port (default: 80/443)
299
+ https?: boolean; // Force HTTPS (default: auto-detect)
300
+ path?: string; // Request path (default: "/")
301
+ headers?: Record<string, string>; // Custom headers
302
+ }
303
+ ```
304
+
305
+ #### TCPDriverOptions
306
+
307
+ ```typescript
308
+ interface TCPDriverOptions {
309
+ port?: number; // Target port (default: 80)
310
+ connectTimeout?: number; // Connection timeout in ms (default: 5000)
311
+ }
312
+ ```
313
+
314
+ #### DNSDriverOptions
315
+
316
+ ```typescript
317
+ interface DNSDriverOptions {
318
+ type?: "A" | "AAAA" | "CNAME" | "MX" | "TXT" | "NS"; // Record type (default: "A")
319
+ servers?: string[]; // DNS servers (default: system DNS)
320
+ }
321
+ ```
322
+
323
+ #### HybridDriverOptions
324
+
325
+ ```typescript
326
+ interface HybridDriverOptions {
327
+ priority?: Array<"http" | "tcp" | "dns">; // Detection priority (default: ["tcp", "http", "dns"])
328
+ }
329
+ ```
330
+
331
+ ## Hybrid Driver Behavior
332
+
333
+ The Hybrid Driver provides intelligent network connectivity detection by trying multiple methods in order:
334
+
335
+ 1. **TCP (First Priority)**: Fastest method, checks port reachability
336
+ 2. **HTTP (Second Priority)**: Confirms application layer availability
337
+ 3. **DNS (Last Priority)**: Basic DNS resolution capability as fallback
338
+
339
+ **Why this order?**
340
+
341
+ - **TCP First**: Closest to traditional ICMP ping, detects IP layer connectivity quickly (~1-5ms)
342
+ - **HTTP Second**: Validates that the service is actually responding at application level (~100-300ms)
343
+ - **DNS Last**: Only checks if domain can be resolved, doesn't guarantee host reachability (~10-20ms)
344
+
345
+ **Custom Priority Example:**
346
+
347
+ ```typescript
348
+ // For web service monitoring - prioritize HTTP
349
+ const webMonitor = createPingManager({
350
+ driver: hybridDriver({ priority: ["http", "tcp", "dns"] }),
351
+ });
352
+
353
+ // For quick connectivity checks - prioritize TCP
354
+ const quickCheck = createPingManager({
355
+ driver: hybridDriver({ priority: ["tcp", "dns", "http"] }),
356
+ });
357
+ ```
358
+
359
+ ## Use Cases
360
+
361
+ ### Web Service Monitoring
362
+
363
+ ```typescript
364
+ const monitor = createPingManager({
365
+ driver: httpDriver({ method: "HEAD", path: "/health" }),
366
+ });
367
+
368
+ setInterval(async () => {
369
+ const results = await monitor.ping("api.example.com");
370
+ if (!results[0].alive) {
371
+ console.error("Service is down!");
372
+ // Trigger alert
373
+ }
374
+ }, 60000); // Check every minute
375
+ ```
376
+
377
+ ### Port Availability Check
378
+
379
+ ```typescript
380
+ const ports = [22, 80, 443, 8080];
381
+
382
+ for (const port of ports) {
383
+ const checker = createPingManager({
384
+ driver: tcpDriver({ port }),
385
+ });
386
+
387
+ const results = await checker.ping("example.com");
388
+ console.log(`Port ${port}: ${results[0].alive ? "Open" : "Closed"}`);
389
+ }
390
+ ```
391
+
392
+ ### Network Diagnostics
393
+
394
+ ```typescript
395
+ const diagnostic = createPingManager({
396
+ driver: hybridDriver({ priority: ["tcp", "http", "dns"] }),
397
+ });
398
+
399
+ const hosts = ["google.com", "github.com", "cloudflare.com"];
400
+
401
+ for (const host of hosts) {
402
+ const results = await diagnostic.ping(host);
403
+ console.log(`${host}: ${results[0].alive ? "✓" : "✗"} ${results[0].time}ms`);
404
+ }
405
+ ```
406
+
407
+ ## License
408
+
409
+ - [MIT](LICENSE) &copy; [Funish](http://www.funish.net/)
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = dnsDriver;
7
+ exports.pingOnceDNS = pingOnceDNS;
8
+ var _dns = require("dns");
9
+ async function pingOnceDNS(resolver, host, type, timeout, sequence) {
10
+ const startTime = Date.now();
11
+ try {
12
+ const timeoutPromise = new Promise((_, reject) => {
13
+ setTimeout(() => reject(new Error("DNS lookup timeout")), timeout);
14
+ });
15
+ await Promise.race([resolver.resolve(host, type), timeoutPromise]);
16
+ return {
17
+ host,
18
+ alive: true,
19
+ time: Date.now() - startTime,
20
+ sequence
21
+ };
22
+ } catch {
23
+ return {
24
+ host,
25
+ alive: false,
26
+ time: Date.now() - startTime,
27
+ sequence
28
+ };
29
+ }
30
+ }
31
+ function dnsDriver(options = {}) {
32
+ const {
33
+ type = "A",
34
+ servers
35
+ } = options;
36
+ const resolver = new _dns.promises.Resolver();
37
+ if (servers) {
38
+ resolver.setServers(servers);
39
+ }
40
+ const ping = async (host, opts) => {
41
+ const count = opts?.count || 1;
42
+ const timeout = opts?.timeout || 5e3;
43
+ const results = [];
44
+ for (let i = 0; i < count; i++) {
45
+ const result = await pingOnceDNS(resolver, host, type, timeout, i + 1);
46
+ results.push(result);
47
+ if (i < count - 1 && opts?.interval) {
48
+ await new Promise(resolve => setTimeout(resolve, opts.interval));
49
+ }
50
+ }
51
+ return results;
52
+ };
53
+ return {
54
+ name: "dns",
55
+ options,
56
+ ping
57
+ };
58
+ }
@@ -0,0 +1,10 @@
1
+ import { promises as dnsPromises } from "dns";
2
+ import type { Driver, DriverOptions, PingResult } from "../types";
3
+ export interface DNSDriverOptions extends DriverOptions {
4
+ /** DNS record type (default: A) */
5
+ type?: "A" | "AAAA" | "CNAME" | "MX" | "TXT" | "NS";
6
+ /** DNS servers */
7
+ servers?: string[];
8
+ }
9
+ export declare function pingOnceDNS(resolver: dnsPromises.Resolver, host: string, type: string, timeout: number, sequence: number): Promise<PingResult>;
10
+ export default function dnsDriver(options?: DNSDriverOptions): Driver;
@@ -0,0 +1,48 @@
1
+ import { promises as dnsPromises } from "dns";
2
+ export async function pingOnceDNS(resolver, host, type, timeout, sequence) {
3
+ const startTime = Date.now();
4
+ try {
5
+ const timeoutPromise = new Promise((_, reject) => {
6
+ setTimeout(() => reject(new Error("DNS lookup timeout")), timeout);
7
+ });
8
+ await Promise.race([resolver.resolve(host, type), timeoutPromise]);
9
+ return {
10
+ host,
11
+ alive: true,
12
+ time: Date.now() - startTime,
13
+ sequence
14
+ };
15
+ } catch {
16
+ return {
17
+ host,
18
+ alive: false,
19
+ time: Date.now() - startTime,
20
+ sequence
21
+ };
22
+ }
23
+ }
24
+ export default function dnsDriver(options = {}) {
25
+ const { type = "A", servers } = options;
26
+ const resolver = new dnsPromises.Resolver();
27
+ if (servers) {
28
+ resolver.setServers(servers);
29
+ }
30
+ const ping = async (host, opts) => {
31
+ const count = opts?.count || 1;
32
+ const timeout = opts?.timeout || 5e3;
33
+ const results = [];
34
+ for (let i = 0; i < count; i++) {
35
+ const result = await pingOnceDNS(resolver, host, type, timeout, i + 1);
36
+ results.push(result);
37
+ if (i < count - 1 && opts?.interval) {
38
+ await new Promise((resolve) => setTimeout(resolve, opts.interval));
39
+ }
40
+ }
41
+ return results;
42
+ };
43
+ return {
44
+ name: "dns",
45
+ options,
46
+ ping
47
+ };
48
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = httpDriver;
7
+ exports.pingOnceHTTP = pingOnceHTTP;
8
+ var _ofetch = require("ofetch");
9
+ async function pingOnceHTTP(host, protocol, port, path, method, timeout, headers, sequence) {
10
+ const startTime = Date.now();
11
+ try {
12
+ const url = `${protocol}://${host}:${port}${path}`;
13
+ await (0, _ofetch.ofetch)(url, {
14
+ method,
15
+ headers,
16
+ timeout
17
+ });
18
+ return {
19
+ host,
20
+ alive: true,
21
+ time: Date.now() - startTime,
22
+ sequence
23
+ };
24
+ } catch {
25
+ return {
26
+ host,
27
+ alive: false,
28
+ time: Date.now() - startTime,
29
+ sequence
30
+ };
31
+ }
32
+ }
33
+ function httpDriver(options = {}) {
34
+ const {
35
+ method = "HEAD",
36
+ path = "/",
37
+ headers = {}
38
+ } = options;
39
+ const ping = async (host, opts) => {
40
+ const count = opts?.count || 1;
41
+ const timeout = opts?.timeout || 5e3;
42
+ const results = [];
43
+ const protocol = options.https ?? options.port === 443 ? "https" : "http";
44
+ const port = options.port || (protocol === "https" ? 443 : 80);
45
+ for (let i = 0; i < count; i++) {
46
+ const result = await pingOnceHTTP(host, protocol, port, path, method, timeout, headers, i + 1);
47
+ results.push(result);
48
+ if (i < count - 1 && opts?.interval) {
49
+ await new Promise(resolve => setTimeout(resolve, opts.interval));
50
+ }
51
+ }
52
+ return results;
53
+ };
54
+ return {
55
+ name: "http",
56
+ options,
57
+ ping
58
+ };
59
+ }
@@ -0,0 +1,15 @@
1
+ import type { Driver, DriverOptions, PingResult } from "../types";
2
+ export interface HTTPDriverOptions extends DriverOptions {
3
+ /** Request method (default: HEAD) */
4
+ method?: "HEAD" | "GET";
5
+ /** Custom port (default: 80/443) */
6
+ port?: number;
7
+ /** Use HTTPS (default: auto detect) */
8
+ https?: boolean;
9
+ /** Request path (default: "/") */
10
+ path?: string;
11
+ /** Custom headers */
12
+ headers?: Record<string, string>;
13
+ }
14
+ export declare function pingOnceHTTP(host: string, protocol: string, port: number, path: string, method: string, timeout: number, headers: Record<string, string>, sequence: number): Promise<PingResult>;
15
+ export default function httpDriver(options?: HTTPDriverOptions): Driver;
@@ -0,0 +1,57 @@
1
+ import { ofetch } from "ofetch";
2
+ export async function pingOnceHTTP(host, protocol, port, path, method, timeout, headers, sequence) {
3
+ const startTime = Date.now();
4
+ try {
5
+ const url = `${protocol}://${host}:${port}${path}`;
6
+ await ofetch(url, {
7
+ method,
8
+ headers,
9
+ timeout
10
+ });
11
+ return {
12
+ host,
13
+ alive: true,
14
+ time: Date.now() - startTime,
15
+ sequence
16
+ };
17
+ } catch {
18
+ return {
19
+ host,
20
+ alive: false,
21
+ time: Date.now() - startTime,
22
+ sequence
23
+ };
24
+ }
25
+ }
26
+ export default function httpDriver(options = {}) {
27
+ const { method = "HEAD", path = "/", headers = {} } = options;
28
+ const ping = async (host, opts) => {
29
+ const count = opts?.count || 1;
30
+ const timeout = opts?.timeout || 5e3;
31
+ const results = [];
32
+ const protocol = options.https ?? options.port === 443 ? "https" : "http";
33
+ const port = options.port || (protocol === "https" ? 443 : 80);
34
+ for (let i = 0; i < count; i++) {
35
+ const result = await pingOnceHTTP(
36
+ host,
37
+ protocol,
38
+ port,
39
+ path,
40
+ method,
41
+ timeout,
42
+ headers,
43
+ i + 1
44
+ );
45
+ results.push(result);
46
+ if (i < count - 1 && opts?.interval) {
47
+ await new Promise((resolve) => setTimeout(resolve, opts.interval));
48
+ }
49
+ }
50
+ return results;
51
+ };
52
+ return {
53
+ name: "http",
54
+ options,
55
+ ping
56
+ };
57
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = hybridDriver;
7
+ function hybridDriver(options = {}) {
8
+ const {
9
+ priority = ["tcp", "http", "dns"]
10
+ } = options;
11
+ const ping = async (host, opts) => {
12
+ const lastError = new Error("All drivers failed");
13
+ for (const driverType of priority) {
14
+ try {
15
+ let driver;
16
+ switch (driverType) {
17
+ case "http":
18
+ {
19
+ const {
20
+ default: httpDriver
21
+ } = await Promise.resolve().then(() => require("./http.cjs"));
22
+ driver = httpDriver(options);
23
+ break;
24
+ }
25
+ case "tcp":
26
+ {
27
+ const {
28
+ default: tcpDriver
29
+ } = await Promise.resolve().then(() => require("./tcp.cjs"));
30
+ driver = tcpDriver(options);
31
+ break;
32
+ }
33
+ case "dns":
34
+ {
35
+ const {
36
+ default: dnsDriver
37
+ } = await Promise.resolve().then(() => require("./dns.cjs"));
38
+ driver = dnsDriver(options);
39
+ break;
40
+ }
41
+ default:
42
+ continue;
43
+ }
44
+ const result = await driver.ping(host, opts);
45
+ return result;
46
+ } catch (error) {
47
+ lastError.cause = error;
48
+ continue;
49
+ }
50
+ }
51
+ throw lastError;
52
+ };
53
+ return {
54
+ name: "hybrid",
55
+ options,
56
+ ping
57
+ };
58
+ }
@@ -0,0 +1,6 @@
1
+ import type { Driver, DriverOptions } from "../types";
2
+ export interface HybridDriverOptions extends DriverOptions {
3
+ /** Priority order of drivers (default: ["tcp", "http", "dns"]) */
4
+ priority?: Array<"http" | "tcp" | "dns">;
5
+ }
6
+ export default function hybridDriver(options?: HybridDriverOptions): Driver;
@@ -0,0 +1,41 @@
1
+ export default function hybridDriver(options = {}) {
2
+ const { priority = ["tcp", "http", "dns"] } = options;
3
+ const ping = async (host, opts) => {
4
+ const lastError = new Error("All drivers failed");
5
+ for (const driverType of priority) {
6
+ try {
7
+ let driver;
8
+ switch (driverType) {
9
+ case "http": {
10
+ const { default: httpDriver } = await import("./http.mjs");
11
+ driver = httpDriver(options);
12
+ break;
13
+ }
14
+ case "tcp": {
15
+ const { default: tcpDriver } = await import("./tcp.mjs");
16
+ driver = tcpDriver(options);
17
+ break;
18
+ }
19
+ case "dns": {
20
+ const { default: dnsDriver } = await import("./dns.mjs");
21
+ driver = dnsDriver(options);
22
+ break;
23
+ }
24
+ default:
25
+ continue;
26
+ }
27
+ const result = await driver.ping(host, opts);
28
+ return result;
29
+ } catch (error) {
30
+ lastError.cause = error;
31
+ continue;
32
+ }
33
+ }
34
+ throw lastError;
35
+ };
36
+ return {
37
+ name: "hybrid",
38
+ options,
39
+ ping
40
+ };
41
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = tcpDriver;
7
+ exports.pingOnceTCP = pingOnceTCP;
8
+ var _net = require("net");
9
+ async function pingOnceTCP(host, port, timeout, sequence) {
10
+ return new Promise(resolve => {
11
+ const socket = new _net.Socket();
12
+ const startTime = Date.now();
13
+ let resolved = false;
14
+ const cleanup = () => {
15
+ if (resolved) return;
16
+ resolved = true;
17
+ socket.destroy();
18
+ };
19
+ socket.setTimeout(timeout, () => {
20
+ cleanup();
21
+ resolve({
22
+ host,
23
+ alive: false,
24
+ time: timeout,
25
+ sequence
26
+ });
27
+ });
28
+ socket.on("connect", () => {
29
+ const time = Date.now() - startTime;
30
+ cleanup();
31
+ resolve({
32
+ host,
33
+ alive: true,
34
+ time,
35
+ sequence
36
+ });
37
+ });
38
+ socket.on("error", () => {
39
+ cleanup();
40
+ resolve({
41
+ host,
42
+ alive: false,
43
+ time: Date.now() - startTime,
44
+ sequence
45
+ });
46
+ });
47
+ socket.connect(port, host);
48
+ });
49
+ }
50
+ function tcpDriver(options = {}) {
51
+ const {
52
+ port = 80,
53
+ connectTimeout = 5e3
54
+ } = options;
55
+ const ping = async (host, opts) => {
56
+ const count = opts?.count || 1;
57
+ const timeout = opts?.timeout || connectTimeout;
58
+ const results = [];
59
+ for (let i = 0; i < count; i++) {
60
+ const result = await pingOnceTCP(host, port, timeout, i + 1);
61
+ results.push(result);
62
+ if (i < count - 1 && opts?.interval) {
63
+ await new Promise(resolve => setTimeout(resolve, opts.interval));
64
+ }
65
+ }
66
+ return results;
67
+ };
68
+ return {
69
+ name: "tcp",
70
+ options,
71
+ ping
72
+ };
73
+ }
@@ -0,0 +1,9 @@
1
+ import type { Driver, DriverOptions, PingResult } from "../types";
2
+ export interface TCPDriverOptions extends DriverOptions {
3
+ /** Target port (default: 80) */
4
+ port?: number;
5
+ /** Connection timeout in ms (default: 5000) */
6
+ connectTimeout?: number;
7
+ }
8
+ export declare function pingOnceTCP(host: string, port: number, timeout: number, sequence: number): Promise<PingResult>;
9
+ export default function tcpDriver(options?: TCPDriverOptions): Driver;
@@ -0,0 +1,63 @@
1
+ import { Socket } from "net";
2
+ export async function pingOnceTCP(host, port, timeout, sequence) {
3
+ return new Promise((resolve) => {
4
+ const socket = new Socket();
5
+ const startTime = Date.now();
6
+ let resolved = false;
7
+ const cleanup = () => {
8
+ if (resolved) return;
9
+ resolved = true;
10
+ socket.destroy();
11
+ };
12
+ socket.setTimeout(timeout, () => {
13
+ cleanup();
14
+ resolve({
15
+ host,
16
+ alive: false,
17
+ time: timeout,
18
+ sequence
19
+ });
20
+ });
21
+ socket.on("connect", () => {
22
+ const time = Date.now() - startTime;
23
+ cleanup();
24
+ resolve({
25
+ host,
26
+ alive: true,
27
+ time,
28
+ sequence
29
+ });
30
+ });
31
+ socket.on("error", () => {
32
+ cleanup();
33
+ resolve({
34
+ host,
35
+ alive: false,
36
+ time: Date.now() - startTime,
37
+ sequence
38
+ });
39
+ });
40
+ socket.connect(port, host);
41
+ });
42
+ }
43
+ export default function tcpDriver(options = {}) {
44
+ const { port = 80, connectTimeout = 5e3 } = options;
45
+ const ping = async (host, opts) => {
46
+ const count = opts?.count || 1;
47
+ const timeout = opts?.timeout || connectTimeout;
48
+ const results = [];
49
+ for (let i = 0; i < count; i++) {
50
+ const result = await pingOnceTCP(host, port, timeout, i + 1);
51
+ results.push(result);
52
+ if (i < count - 1 && opts?.interval) {
53
+ await new Promise((resolve) => setTimeout(resolve, opts.interval));
54
+ }
55
+ }
56
+ return results;
57
+ };
58
+ return {
59
+ name: "tcp",
60
+ options,
61
+ ping
62
+ };
63
+ }
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";function createPingManager(r){const{driver:n}=r;return{ping:async(e,t)=>{if(!n.ping)throw new Error("Driver does not implement ping method");return await n.ping(e,t)}}}exports.createPingManager=createPingManager;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * UnPing Types
3
+ * Unified network ping library with multi-driver support
4
+ */
5
+ interface PingResult {
6
+ /** Target host */
7
+ host: string;
8
+ /** Is alive */
9
+ alive: boolean;
10
+ /** Response time (ms) */
11
+ time: number;
12
+ /** Sequence number */
13
+ sequence?: number;
14
+ /** TTL */
15
+ ttl?: number;
16
+ }
17
+ interface DriverOptions {
18
+ [key: string]: any;
19
+ }
20
+ interface PingOptions {
21
+ /** Ping count (default: 1) */
22
+ count?: number;
23
+ /** Timeout in ms (default: 5000) */
24
+ timeout?: number;
25
+ /** Packet size in bytes */
26
+ size?: number;
27
+ /** Interval between pings in ms */
28
+ interval?: number;
29
+ }
30
+ type MaybePromise<T> = T | Promise<T>;
31
+ interface Driver<OptionsT = DriverOptions> {
32
+ name?: string;
33
+ options?: OptionsT;
34
+ ping?: (host: string, options?: PingOptions) => MaybePromise<PingResult[]>;
35
+ }
36
+ interface PingManagerOptions {
37
+ driver: Driver;
38
+ }
39
+
40
+ /**
41
+ * UnPing - Unified network ping library
42
+ * A comprehensive ping library with multi-driver support
43
+ */
44
+
45
+ declare function createPingManager(options: PingManagerOptions): {
46
+ /**
47
+ * Ping a host - always returns array
48
+ */
49
+ ping: (host: string, opts?: PingOptions) => Promise<PingResult[]>;
50
+ };
51
+
52
+ export { createPingManager };
53
+ export type { Driver, DriverOptions, MaybePromise, PingManagerOptions, PingOptions, PingResult };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * UnPing Types
3
+ * Unified network ping library with multi-driver support
4
+ */
5
+ interface PingResult {
6
+ /** Target host */
7
+ host: string;
8
+ /** Is alive */
9
+ alive: boolean;
10
+ /** Response time (ms) */
11
+ time: number;
12
+ /** Sequence number */
13
+ sequence?: number;
14
+ /** TTL */
15
+ ttl?: number;
16
+ }
17
+ interface DriverOptions {
18
+ [key: string]: any;
19
+ }
20
+ interface PingOptions {
21
+ /** Ping count (default: 1) */
22
+ count?: number;
23
+ /** Timeout in ms (default: 5000) */
24
+ timeout?: number;
25
+ /** Packet size in bytes */
26
+ size?: number;
27
+ /** Interval between pings in ms */
28
+ interval?: number;
29
+ }
30
+ type MaybePromise<T> = T | Promise<T>;
31
+ interface Driver<OptionsT = DriverOptions> {
32
+ name?: string;
33
+ options?: OptionsT;
34
+ ping?: (host: string, options?: PingOptions) => MaybePromise<PingResult[]>;
35
+ }
36
+ interface PingManagerOptions {
37
+ driver: Driver;
38
+ }
39
+
40
+ /**
41
+ * UnPing - Unified network ping library
42
+ * A comprehensive ping library with multi-driver support
43
+ */
44
+
45
+ declare function createPingManager(options: PingManagerOptions): {
46
+ /**
47
+ * Ping a host - always returns array
48
+ */
49
+ ping: (host: string, opts?: PingOptions) => Promise<PingResult[]>;
50
+ };
51
+
52
+ export { createPingManager };
53
+ export type { Driver, DriverOptions, MaybePromise, PingManagerOptions, PingOptions, PingResult };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * UnPing Types
3
+ * Unified network ping library with multi-driver support
4
+ */
5
+ interface PingResult {
6
+ /** Target host */
7
+ host: string;
8
+ /** Is alive */
9
+ alive: boolean;
10
+ /** Response time (ms) */
11
+ time: number;
12
+ /** Sequence number */
13
+ sequence?: number;
14
+ /** TTL */
15
+ ttl?: number;
16
+ }
17
+ interface DriverOptions {
18
+ [key: string]: any;
19
+ }
20
+ interface PingOptions {
21
+ /** Ping count (default: 1) */
22
+ count?: number;
23
+ /** Timeout in ms (default: 5000) */
24
+ timeout?: number;
25
+ /** Packet size in bytes */
26
+ size?: number;
27
+ /** Interval between pings in ms */
28
+ interval?: number;
29
+ }
30
+ type MaybePromise<T> = T | Promise<T>;
31
+ interface Driver<OptionsT = DriverOptions> {
32
+ name?: string;
33
+ options?: OptionsT;
34
+ ping?: (host: string, options?: PingOptions) => MaybePromise<PingResult[]>;
35
+ }
36
+ interface PingManagerOptions {
37
+ driver: Driver;
38
+ }
39
+
40
+ /**
41
+ * UnPing - Unified network ping library
42
+ * A comprehensive ping library with multi-driver support
43
+ */
44
+
45
+ declare function createPingManager(options: PingManagerOptions): {
46
+ /**
47
+ * Ping a host - always returns array
48
+ */
49
+ ping: (host: string, opts?: PingOptions) => Promise<PingResult[]>;
50
+ };
51
+
52
+ export { createPingManager };
53
+ export type { Driver, DriverOptions, MaybePromise, PingManagerOptions, PingOptions, PingResult };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ function t(r){const{driver:n}=r;return{ping:async(e,i)=>{if(!n.ping)throw new Error("Driver does not implement ping method");return await n.ping(e,i)}}}export{t as createPingManager};
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "unping",
3
+ "version": "0.0.0",
4
+ "description": "Unified network ping library with multi-driver support",
5
+ "main": "dist/index.mjs",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./drivers/*": {
16
+ "import": "./dist/drivers/*.mjs",
17
+ "require": "./dist/drivers/*.cjs",
18
+ "types": "./dist/drivers/*.d.ts"
19
+ }
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/funish/axis.git"
24
+ },
25
+ "keywords": [
26
+ "ping",
27
+ "network",
28
+ "tcp",
29
+ "http",
30
+ "dns",
31
+ "latency",
32
+ "monitoring",
33
+ "connectivity",
34
+ "typescript"
35
+ ],
36
+ "author": {
37
+ "name": "Funish",
38
+ "email": "contact@funish.net",
39
+ "url": "http://www.funish.net/"
40
+ },
41
+ "license": "MIT",
42
+ "bugs": {
43
+ "url": "https://github.com/funish/axis/issues"
44
+ },
45
+ "homepage": "https://github.com/funish/axis#readme",
46
+ "dependencies": {
47
+ "ofetch": "1.4.1"
48
+ },
49
+ "scripts": {
50
+ "dev": "unbuild --stub",
51
+ "build": "unbuild"
52
+ }
53
+ }