icanhazip-client 1.1.0 → 1.2.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/README.md +1 -0
- package/package.json +4 -2
- package/dist/get-full-trace/test/index.test.d.ts +0 -2
- package/dist/get-full-trace/test/index.test.d.ts.map +0 -1
- package/dist/get-full-trace/test/index.test.js +0 -75
- package/dist/get-full-trace/test/index.test.js.map +0 -1
- package/dist/get-ipv4/test/index.test.d.ts +0 -2
- package/dist/get-ipv4/test/index.test.d.ts.map +0 -1
- package/dist/get-ipv4/test/index.test.js +0 -46
- package/dist/get-ipv4/test/index.test.js.map +0 -1
- package/dist/get-ipv6/test/index.test.d.ts +0 -2
- package/dist/get-ipv6/test/index.test.d.ts.map +0 -1
- package/dist/get-ipv6/test/index.test.js +0 -50
- package/dist/get-ipv6/test/index.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|

|
|
3
3
|

|
|
4
4
|

|
|
5
|
+

|
|
5
6
|
# Icanhazip Client
|
|
6
7
|
A lightweight JavaScript/TypeScript client for retrieving public IP information using the icanhazip service. This package is **ESM-only** and works in modern browsers and Node.js 18+ environments that support the Fetch API. Provides support for [https://github.com/runvnc/icanhazip](https://github.com/runvnc/icanhazip)
|
|
7
8
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "icanhazip-client",
|
|
3
3
|
"description": "Tiny fetch-based client for icanhazip.com (IPv4, IPv6, trace)",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.2.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
+
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
16
|
+
"prebuild": "npm run clean",
|
|
15
17
|
"build": "tsc",
|
|
16
18
|
"prepublishOnly": "npm run build",
|
|
17
19
|
"test": "jest",
|
|
@@ -32,7 +34,7 @@
|
|
|
32
34
|
"devDependencies": {
|
|
33
35
|
"@types/jest": "^29.5.14",
|
|
34
36
|
"jest": "^29.7.0",
|
|
35
|
-
"jest-environment-jsdom": "^
|
|
37
|
+
"jest-environment-jsdom": "^30.4.1",
|
|
36
38
|
"ts-jest": "^29.4.6",
|
|
37
39
|
"typescript": "^5.9.3"
|
|
38
40
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/get-full-trace/test/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/// <reference types="jest" />
|
|
2
|
-
import { getFullTrace } from "../index.js";
|
|
3
|
-
/* restore mocks after each test */
|
|
4
|
-
afterEach(() => {
|
|
5
|
-
jest.restoreAllMocks();
|
|
6
|
-
});
|
|
7
|
-
describe("getFullTrace", () => {
|
|
8
|
-
const originalFetch = global.fetch;
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
if (originalFetch)
|
|
11
|
-
global.fetch = originalFetch;
|
|
12
|
-
else
|
|
13
|
-
delete global.fetch;
|
|
14
|
-
jest.restoreAllMocks();
|
|
15
|
-
});
|
|
16
|
-
/* #1 */
|
|
17
|
-
test("throws when global fetch is unavailable", async () => {
|
|
18
|
-
delete global.fetch;
|
|
19
|
-
await expect(getFullTrace()).rejects.toThrow("[Bad]: Global Fetch Not Available");
|
|
20
|
-
});
|
|
21
|
-
/* #2 */
|
|
22
|
-
test("throws when fetch response is not ok", async () => {
|
|
23
|
-
const mockResponse = {
|
|
24
|
-
ok: false,
|
|
25
|
-
text: jest.fn().mockResolvedValue("")
|
|
26
|
-
};
|
|
27
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
28
|
-
await expect(getFullTrace()).rejects.toThrow("[Bad]: getIPV4 Fetch Error");
|
|
29
|
-
});
|
|
30
|
-
/* #3 */
|
|
31
|
-
test("returns parsed trace data", async () => {
|
|
32
|
-
const trace = [
|
|
33
|
-
"ip=1.2.3.4",
|
|
34
|
-
"loc=US",
|
|
35
|
-
"tls=TLSv1.3",
|
|
36
|
-
"http=http/2",
|
|
37
|
-
"sni=plaintext"
|
|
38
|
-
].join("\n");
|
|
39
|
-
const mockResponse = {
|
|
40
|
-
ok: true,
|
|
41
|
-
text: jest.fn().mockResolvedValue(trace)
|
|
42
|
-
};
|
|
43
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
44
|
-
await expect(getFullTrace()).resolves.toEqual({
|
|
45
|
-
ip: "1.2.3.4",
|
|
46
|
-
loc: "US",
|
|
47
|
-
tls: "TLSv1.3",
|
|
48
|
-
http: "http/2",
|
|
49
|
-
sni: "plaintext"
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
/* #4 */
|
|
53
|
-
test("ignores malformed lines", async () => {
|
|
54
|
-
const trace = ["ip=1.2.3.4", "badline", "loc=US", "=noval", "k="]
|
|
55
|
-
.join("\n");
|
|
56
|
-
const mockResponse = {
|
|
57
|
-
ok: true,
|
|
58
|
-
text: jest.fn().mockResolvedValue(trace)
|
|
59
|
-
};
|
|
60
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
61
|
-
const res = await getFullTrace();
|
|
62
|
-
expect(res).toEqual({ ip: "1.2.3.4", loc: "US", k: "" });
|
|
63
|
-
});
|
|
64
|
-
/* #5 */
|
|
65
|
-
test("targets the trace endpoint", async () => {
|
|
66
|
-
const mockResponse = {
|
|
67
|
-
ok: true,
|
|
68
|
-
text: jest.fn().mockResolvedValue("ip=1.2.3.4")
|
|
69
|
-
};
|
|
70
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
71
|
-
await getFullTrace();
|
|
72
|
-
expect(global.fetch).toHaveBeenCalledWith("https://icanhazip.com/cdn-cgi/trace");
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
//# sourceMappingURL=index.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/get-full-trace/test/index.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/get-ipv4/test/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/// <reference types="jest" />
|
|
2
|
-
import { getIPV4 } from '../index.js';
|
|
3
|
-
describe('getIPV4', () => {
|
|
4
|
-
const originalFetch = global.fetch;
|
|
5
|
-
afterEach(() => {
|
|
6
|
-
if (originalFetch)
|
|
7
|
-
global.fetch = originalFetch;
|
|
8
|
-
else
|
|
9
|
-
delete global.fetch;
|
|
10
|
-
jest.restoreAllMocks();
|
|
11
|
-
});
|
|
12
|
-
/* #1 */
|
|
13
|
-
test('throws when global fetch is unavailable', async () => {
|
|
14
|
-
delete global.fetch;
|
|
15
|
-
await expect(getIPV4()).rejects.toThrow('[Bad]: Global Fetch Not Available');
|
|
16
|
-
});
|
|
17
|
-
/* #2 */
|
|
18
|
-
test('throws when fetch response is not ok', async () => {
|
|
19
|
-
const mockResponse = {
|
|
20
|
-
ok: false,
|
|
21
|
-
text: jest.fn().mockResolvedValue('1.2.3.4'),
|
|
22
|
-
};
|
|
23
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
24
|
-
await expect(getIPV4()).rejects.toThrow('[Bad]: getIPV4 Fetch Error');
|
|
25
|
-
});
|
|
26
|
-
/* #3 */
|
|
27
|
-
test('returns trimmed ipv4 string', async () => {
|
|
28
|
-
const mockResponse = {
|
|
29
|
-
ok: true,
|
|
30
|
-
text: jest.fn().mockResolvedValue('1.2.3.4\n'),
|
|
31
|
-
};
|
|
32
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
33
|
-
await expect(getIPV4()).resolves.toEqual({ ipv4: '1.2.3.4' });
|
|
34
|
-
});
|
|
35
|
-
/* #4 */
|
|
36
|
-
test('targets the ipv4 endpoint', async () => {
|
|
37
|
-
const mockResponse = {
|
|
38
|
-
ok: true,
|
|
39
|
-
text: jest.fn().mockResolvedValue('1.2.3.4'),
|
|
40
|
-
};
|
|
41
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
42
|
-
await getIPV4();
|
|
43
|
-
expect(global.fetch).toHaveBeenCalledWith('https://ipv4.icanhazip.com/');
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
//# sourceMappingURL=index.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/get-ipv4/test/index.test.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,MAAM,aAAa,GAAI,MAAc,CAAC,KAAK,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,aAAa;YAAG,MAAc,CAAC,KAAK,GAAG,aAAa,CAAC;;YACpD,OAAQ,MAAc,CAAC,KAAK,CAAC;QAClC,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,QAAQ;IACR,IAAI,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACzD,OAAQ,MAAc,CAAC,KAAK,CAAC;QAE7B,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CACrC,mCAAmC,CACpC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ;IACR,IAAI,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,YAAY,GAAG;YACnB,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;SAC7C,CAAC;QACD,MAAc,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAElE,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,QAAQ;IACR,IAAI,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,YAAY,GAAG;YACnB,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC;SAC/C,CAAC;QACD,MAAc,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAElE,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,QAAQ;IACR,IAAI,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,YAAY,GAAG;YACnB,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;SAC7C,CAAC;QACD,MAAc,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAElE,MAAM,OAAO,EAAE,CAAC;QAChB,MAAM,CAAE,MAAc,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAChD,6BAA6B,CAC9B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/get-ipv6/test/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/// <reference types="jest" />
|
|
2
|
-
import { getIPV6 } from "../index.js";
|
|
3
|
-
/* restore mocks after each test */
|
|
4
|
-
afterEach(() => {
|
|
5
|
-
jest.restoreAllMocks();
|
|
6
|
-
});
|
|
7
|
-
describe("getIPV6", () => {
|
|
8
|
-
const originalFetch = global.fetch;
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
if (originalFetch)
|
|
11
|
-
global.fetch = originalFetch;
|
|
12
|
-
else
|
|
13
|
-
delete global.fetch;
|
|
14
|
-
jest.restoreAllMocks();
|
|
15
|
-
});
|
|
16
|
-
/* #1 */
|
|
17
|
-
test("throws when global fetch is unavailable", async () => {
|
|
18
|
-
delete global.fetch;
|
|
19
|
-
await expect(getIPV6()).rejects.toThrow("[Bad]: Global Fetch Not Available");
|
|
20
|
-
});
|
|
21
|
-
/* #2 */
|
|
22
|
-
test("throws when fetch response is not ok", async () => {
|
|
23
|
-
const mockResponse = {
|
|
24
|
-
ok: false,
|
|
25
|
-
text: jest.fn().mockResolvedValue("2001:db8::1")
|
|
26
|
-
};
|
|
27
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
28
|
-
await expect(getIPV6()).rejects.toThrow("[Bad]: getIPV6 Fetch Error");
|
|
29
|
-
});
|
|
30
|
-
/* #3 */
|
|
31
|
-
test("returns trimmed ipv6 string", async () => {
|
|
32
|
-
const mockResponse = {
|
|
33
|
-
ok: true,
|
|
34
|
-
text: jest.fn().mockResolvedValue("2001:db8::1\n")
|
|
35
|
-
};
|
|
36
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
37
|
-
await expect(getIPV6()).resolves.toEqual({ ipv6: "2001:db8::1" });
|
|
38
|
-
});
|
|
39
|
-
/* #4 */
|
|
40
|
-
test("targets the ipv6 endpoint", async () => {
|
|
41
|
-
const mockResponse = {
|
|
42
|
-
ok: true,
|
|
43
|
-
text: jest.fn().mockResolvedValue("2001:db8::1")
|
|
44
|
-
};
|
|
45
|
-
global.fetch = jest.fn().mockResolvedValue(mockResponse);
|
|
46
|
-
await getIPV6();
|
|
47
|
-
expect(global.fetch).toHaveBeenCalledWith("https://ipv6.icanhazip.com/");
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
//# sourceMappingURL=index.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/get-ipv6/test/index.test.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,mCAAmC;AACnC,SAAS,CAAC,GAAG,EAAE;IACb,IAAI,CAAC,eAAe,EAAE,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,MAAM,aAAa,GAAI,MAAc,CAAC,KAAK,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,aAAa;YAAG,MAAc,CAAC,KAAK,GAAG,aAAa,CAAC;;YACpD,OAAQ,MAAc,CAAC,KAAK,CAAC;QAClC,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,QAAQ;IACR,IAAI,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACzD,OAAQ,MAAc,CAAC,KAAK,CAAC;QAE7B,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,QAAQ;IACR,IAAI,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,YAAY,GAAG;YACnB,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,aAAa,CAAC;SACjD,CAAC;QACD,MAAc,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAElE,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,QAAQ;IACR,IAAI,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,YAAY,GAAG;YACnB,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,eAAe,CAAC;SACnD,CAAC;QACD,MAAc,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAElE,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,QAAQ;IACR,IAAI,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,YAAY,GAAG;YACnB,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,aAAa,CAAC;SACjD,CAAC;QACD,MAAc,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAElE,MAAM,OAAO,EAAE,CAAC;QAChB,MAAM,CAAE,MAAc,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAChD,6BAA6B,CAC9B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|