@prosopo/ipinfo 0.2.40 → 0.3.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.
Files changed (52) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +12 -10
  2. package/.turbo/turbo-build$colon$tsc.log +10 -10
  3. package/.turbo/turbo-build.log +14 -11
  4. package/CHANGELOG.md +19 -0
  5. package/dist/IpInfoService.d.ts +8 -1
  6. package/dist/IpInfoService.d.ts.map +1 -1
  7. package/dist/IpInfoService.js +77 -84
  8. package/dist/IpInfoService.js.map +1 -1
  9. package/dist/_virtual/_rolldown/runtime.js +3 -0
  10. package/dist/backends/ipapi.d.ts +6 -0
  11. package/dist/backends/ipapi.d.ts.map +1 -1
  12. package/dist/backends/ipapi.js +117 -104
  13. package/dist/backends/ipapi.js.map +1 -1
  14. package/dist/backends/maxmind.d.ts +4 -0
  15. package/dist/backends/maxmind.d.ts.map +1 -1
  16. package/dist/backends/maxmind.js +126 -145
  17. package/dist/backends/maxmind.js.map +1 -1
  18. package/dist/cjs/IpInfoService.cjs +80 -86
  19. package/dist/cjs/backends/ipapi.cjs +118 -104
  20. package/dist/cjs/backends/maxmind.cjs +124 -165
  21. package/dist/cjs/index.cjs +7 -3
  22. package/dist/index.d.ts +6 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +5 -4
  25. package/dist/index.js.map +1 -1
  26. package/dist/tests/ipInfoService.unit.test.d.ts +2 -0
  27. package/dist/tests/ipInfoService.unit.test.d.ts.map +1 -0
  28. package/dist/tests/ipInfoService.unit.test.js +244 -0
  29. package/dist/tests/ipInfoService.unit.test.js.map +1 -0
  30. package/dist/tests/ipapi.unit.test.d.ts +2 -0
  31. package/dist/tests/ipapi.unit.test.d.ts.map +1 -0
  32. package/dist/tests/ipapi.unit.test.js +337 -0
  33. package/dist/tests/ipapi.unit.test.js.map +1 -0
  34. package/dist/tests/ipinfo.test-d.d.ts +2 -0
  35. package/dist/tests/ipinfo.test-d.d.ts.map +1 -0
  36. package/dist/tests/ipinfo.test-d.js +97 -0
  37. package/dist/tests/ipinfo.test-d.js.map +1 -0
  38. package/dist/tests/maxmind.unit.test.d.ts +2 -0
  39. package/dist/tests/maxmind.unit.test.d.ts.map +1 -0
  40. package/dist/tests/maxmind.unit.test.js +391 -0
  41. package/dist/tests/maxmind.unit.test.js.map +1 -0
  42. package/package.json +10 -8
  43. package/src/IpInfoService.ts +19 -2
  44. package/src/backends/ipapi.ts +57 -10
  45. package/src/backends/maxmind.ts +22 -4
  46. package/src/index.ts +9 -1
  47. package/src/tests/ipInfoService.unit.test.ts +422 -0
  48. package/src/tests/ipapi.unit.test.ts +509 -0
  49. package/src/tests/ipinfo.test-d.ts +189 -0
  50. package/src/tests/maxmind.unit.test.ts +562 -0
  51. package/tsconfig.tsbuildinfo +1 -1
  52. package/vite.test.config.ts +18 -0
@@ -1,5 +1,5 @@
1
1
 
2
- > @prosopo/ipinfo@0.2.40 build:cjs
2
+ > @prosopo/ipinfo@0.3.0 build:cjs
3
3
  > NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
4
4
 
5
5
  ViteCommonJSConfig: .
@@ -12,6 +12,7 @@ ViteCommonJSConfig: .
12
12
  '/home/runner/work/captcha/captcha/packages/util-crypto/tsconfig.json'
13
13
  ]
14
14
  }
15
+ The plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the resolve.tsconfigPaths option. You can remove the plugin and set resolve.tsconfigPaths: true in your Vite config instead.
15
16
  {
16
17
  externals: [
17
18
  '@prosopo/logger',
@@ -21,14 +22,15 @@ ViteCommonJSConfig: .
21
22
  '@prosopo/util-crypto'
22
23
  ]
23
24
  }
24
- vite v6.4.1 building SSR bundle for production...
25
+ vite v8.1.5 building ssr environment for production...
25
26
  Bundle build started
26
- transforming...
27
- Build end
28
- ✓ 4 modules transformed.
27
+ 
28
+ ✓ 5 modules transformed.
29
29
  rendering chunks...
30
- dist/cjs/index.cjs 0.19 kB
31
- dist/cjs/IpInfoService.cjs 2.77 kB
32
- dist/cjs/backends/ipapi.cjs 3.30 kB
33
- dist/cjs/backends/maxmind.cjs 5.70 kB
34
- ✓ built in 183ms
30
+ computing gzip size...
31
+ dist/cjs/index.cjs 0.47 kB │ gzip: 0.21 kB
32
+ dist/cjs/IpInfoService.cjs 2.80 kB │ gzip: 0.98 kB
33
+ dist/cjs/backends/maxmind.cjs 3.82 kB │ gzip: 1.14 kB
34
+ dist/cjs/backends/ipapi.cjs 4.11 kB │ gzip: 1.75 kB
35
+
36
+ ✓ built in 63ms
@@ -1,8 +1,8 @@
1
1
 
2
- > @prosopo/ipinfo@0.2.40 build:tsc
2
+ > @prosopo/ipinfo@0.3.0 build:tsc
3
3
  > tsc --build --verbose
4
4
 
5
- 10:22:15 PM - Projects in this build:
5
+ 8:59:04 PM - Projects in this build:
6
6
  * ../../dev/config/tsconfig.json
7
7
  * ../util/tsconfig.json
8
8
  * ../logger/tsconfig.json
@@ -11,19 +11,19 @@
11
11
  * ../types/tsconfig.json
12
12
  * tsconfig.json
13
13
 
14
- 10:22:15 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
14
+ 8:59:04 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
15
15
 
16
- 10:22:15 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
16
+ 8:59:04 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
17
17
 
18
- 10:22:15 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
18
+ 8:59:04 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
19
19
 
20
- 10:22:15 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
20
+ 8:59:04 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
21
21
 
22
- 10:22:15 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
22
+ 8:59:04 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
23
23
 
24
- 10:22:15 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/procaptcha/api.ts' is older than output '../types/tsconfig.tsbuildinfo'
24
+ 8:59:04 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/provider/api.ts' is older than output '../types/tsconfig.tsbuildinfo'
25
25
 
26
- 10:22:15 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
26
+ 8:59:04 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
27
27
 
28
- 10:22:15 PM - Building project '/home/runner/work/captcha/captcha/packages/ipinfo/tsconfig.json'...
28
+ 8:59:04 PM - Building project '/home/runner/work/captcha/captcha/packages/ipinfo/tsconfig.json'...
29
29
 
@@ -1,9 +1,9 @@
1
1
 
2
- > @prosopo/ipinfo@0.2.40 build
2
+ > @prosopo/ipinfo@0.3.0 build
3
3
  > npm run build:cross-env -- --mode ${NODE_ENV:-development}
4
4
 
5
5
 
6
- > @prosopo/ipinfo@0.2.40 build:cross-env
6
+ > @prosopo/ipinfo@0.3.0 build:cross-env
7
7
  > vite build --config vite.esm.config.ts --mode production
8
8
 
9
9
  ViteEsmConfig: .
@@ -25,14 +25,17 @@ ViteEsmConfig: .
25
25
  '@prosopo/util-crypto'
26
26
  ]
27
27
  }
28
- vite v6.4.1 building SSR bundle for production...
28
+ The plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the resolve.tsconfigPaths option. You can remove the plugin and set resolve.tsconfigPaths: true in your Vite config instead.
29
+ vite v8.1.5 building ssr environment for production...
29
30
  Bundle build started
30
- transforming...
31
- Build end
32
- ✓ 4 modules transformed.
31
+ 
32
+ ✓ 5 modules transformed.
33
33
  rendering chunks...
34
- dist/index.js 0.08 kB
35
- dist/IpInfoService.js 2.67 kB
36
- dist/backends/ipapi.js 3.20 kB
37
- dist/backends/maxmind.js 4.44 kB
38
- ✓ built in 184ms
34
+ computing gzip size...
35
+ dist/_virtual/_rolldown/runtime.js 0.04 kB │ gzip: 0.06 kB
36
+ dist/index.js 0.28 kB │ gzip: 0.15 kB
37
+ dist/IpInfoService.js 2.73 kB │ gzip: 0.97 kB
38
+ dist/backends/maxmind.js 3.80 kB │ gzip: 1.14 kB
39
+ dist/backends/ipapi.js 4.07 kB │ gzip: 1.75 kB
40
+
41
+ ✓ built in 80ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @prosopo/ipinfo
2
2
 
3
+ ## 0.3.0
4
+ ### Minor Changes
5
+
6
+ - 270a8d8: Add unit and type tests for `@prosopo/ipinfo`, with the injection seams needed to write them.
7
+
8
+ - `IpapiBackend` accepts an injected `fetch` and a configurable `timeoutMs`; `MaxMindBackend` accepts an injected `openReader`; `IpInfoService` accepts injected backends.
9
+ - `parseAbuserScore` no longer throws when the upstream omits `abuser_score`. The field is declared required by the response type but is not validated on the wire, and a missing value used to turn an otherwise successful lookup into a generic "Network or parsing error".
10
+ - `IPInfoResult.isValid` is now the literal `true` rather than `boolean`, making `IPInfoResponse` an actually discriminated union. Previously `if (!res.isValid)` narrowed to nothing, so `res.error` did not compile and consumers had to cast.
11
+ - The backends, their config types and the injection seams are re-exported from the package entrypoint, along with `isNonRoutable`.
12
+
13
+ ### Patch Changes
14
+
15
+ - e14fce6: chore(deps): bump vite to 6.4.3 and mongoose to 8.24.1, and adjust types for the mongoose 8.24 Document/ObjectId changes
16
+ - Updated dependencies [103318c]
17
+ - Updated dependencies [270a8d8]
18
+ - Updated dependencies [e14fce6]
19
+ - @prosopo/types@4.10.0
20
+ - @prosopo/logger@2.0.4
21
+
3
22
  ## 0.2.40
4
23
  ### Patch Changes
5
24
 
@@ -1,10 +1,17 @@
1
1
  import type { IPInfoResponse } from "@prosopo/types";
2
+ import { IpapiBackend } from "./backends/ipapi.js";
3
+ import { MaxMindBackend } from "./backends/maxmind.js";
2
4
  import type { IIpInfoService, IpInfoServiceConfig } from "./types.js";
5
+ export declare function isNonRoutable(ip: string): boolean;
6
+ export interface IpInfoBackends {
7
+ maxmind?: MaxMindBackend | null;
8
+ ipapi?: IpapiBackend | null;
9
+ }
3
10
  export declare class IpInfoService implements IIpInfoService {
4
11
  private maxmindBackend;
5
12
  private ipapiBackend;
6
13
  private config;
7
- constructor(config: IpInfoServiceConfig);
14
+ constructor(config: IpInfoServiceConfig, backends?: IpInfoBackends);
8
15
  initialize(): Promise<void>;
9
16
  isAvailable(): boolean;
10
17
  lookup(ip: string): Promise<IPInfoResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"IpInfoService.d.ts","sourceRoot":"","sources":["../src/IpInfoService.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAuCtE,qBAAa,aAAc,YAAW,cAAc;IACnD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAoBjC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAcjC,WAAW,IAAI,OAAO;IAOhB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CA4CjD"}
1
+ {"version":3,"file":"IpInfoService.d.ts","sourceRoot":"","sources":["../src/IpInfoService.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAMtE,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CA+BjD;AAQD,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B;AAED,qBAAa,aAAc,YAAW,cAAc;IACnD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,cAAc;IA0B5D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAcjC,WAAW,IAAI,OAAO;IAOhB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CA4CjD"}
@@ -1,89 +1,82 @@
1
1
  import { IpapiBackend } from "./backends/ipapi.js";
2
2
  import { MaxMindBackend } from "./backends/maxmind.js";
3
+ //#region src/IpInfoService.ts
4
+ /**
5
+ * Returns true for loopback, link-local, and private-range IPs that will
6
+ * never yield useful geolocation or threat data from any backend.
7
+ */
3
8
  function isNonRoutable(ip) {
4
- const normalized = ip.replace(/^::ffff:/i, "");
5
- if (normalized.startsWith("127.") || normalized.startsWith("10.") || normalized.startsWith("192.168.") || normalized.startsWith("169.254.") || normalized === "0.0.0.0") {
6
- return true;
7
- }
8
- if (normalized.startsWith("172.")) {
9
- const second = Number.parseInt(normalized.split(".")[1] ?? "", 10);
10
- if (second >= 16 && second <= 31) return true;
11
- }
12
- if (normalized === "::1" || normalized === "::") return true;
13
- if (/^f[cd]/i.test(normalized)) return true;
14
- if (/^fe[89ab]/i.test(normalized)) return true;
15
- return false;
9
+ const normalized = ip.replace(/^::ffff:/i, "");
10
+ if (normalized.startsWith("127.") || normalized.startsWith("10.") || normalized.startsWith("192.168.") || normalized.startsWith("169.254.") || normalized === "0.0.0.0") return true;
11
+ if (normalized.startsWith("172.")) {
12
+ const second = Number.parseInt(normalized.split(".")[1] ?? "", 10);
13
+ if (second >= 16 && second <= 31) return true;
14
+ }
15
+ if (normalized === "::1" || normalized === "::") return true;
16
+ if (/^f[cd]/i.test(normalized)) return true;
17
+ if (/^fe[89ab]/i.test(normalized)) return true;
18
+ return false;
16
19
  }
17
- class IpInfoService {
18
- constructor(config) {
19
- this.maxmindBackend = null;
20
- this.ipapiBackend = null;
21
- this.config = config;
22
- if (config.maxmindCityDbPath || config.maxmindAsnDbPath) {
23
- this.maxmindBackend = new MaxMindBackend({
24
- cityDbPath: config.maxmindCityDbPath,
25
- asnDbPath: config.maxmindAsnDbPath,
26
- logger: config.logger
27
- });
28
- }
29
- if (config.ipapiUrl) {
30
- this.ipapiBackend = new IpapiBackend({
31
- baseUrl: config.ipapiUrl,
32
- apiKey: config.ipapiKey,
33
- logger: config.logger
34
- });
35
- }
36
- }
37
- async initialize() {
38
- if (this.maxmindBackend) {
39
- await this.maxmindBackend.initialize();
40
- }
41
- this.config.logger?.info(() => ({
42
- msg: "IpInfoService initialized",
43
- data: {
44
- maxmindAvailable: this.maxmindBackend?.isAvailable() ?? false,
45
- ipapiAvailable: this.ipapiBackend?.isAvailable() ?? false
46
- }
47
- }));
48
- }
49
- isAvailable() {
50
- return (this.maxmindBackend?.isAvailable() ?? false) || (this.ipapiBackend?.isAvailable() ?? false);
51
- }
52
- async lookup(ip) {
53
- if (isNonRoutable(ip)) {
54
- return {
55
- isValid: false,
56
- error: "Non-routable IP address",
57
- ip
58
- };
59
- }
60
- if (this.ipapiBackend?.isAvailable()) {
61
- const result = await this.ipapiBackend.lookup(ip);
62
- if (result.isValid) {
63
- return result;
64
- }
65
- this.config.logger?.debug(() => ({
66
- msg: "ipapi.is lookup failed, falling back to MaxMind",
67
- data: {
68
- ip,
69
- error: "error" in result ? result.error : "unknown"
70
- }
71
- }));
72
- if (this.maxmindBackend?.isAvailable()) {
73
- return this.maxmindBackend.lookup(ip);
74
- }
75
- return result;
76
- }
77
- if (this.maxmindBackend?.isAvailable()) {
78
- return this.maxmindBackend.lookup(ip);
79
- }
80
- return {
81
- isValid: false,
82
- error: "No IP info backend available",
83
- ip
84
- };
85
- }
86
- }
87
- export {
88
- IpInfoService
20
+ var IpInfoService = class {
21
+ constructor(config, backends) {
22
+ this.maxmindBackend = null;
23
+ this.ipapiBackend = null;
24
+ this.config = config;
25
+ if (backends) {
26
+ this.maxmindBackend = backends.maxmind ?? null;
27
+ this.ipapiBackend = backends.ipapi ?? null;
28
+ return;
29
+ }
30
+ if (config.maxmindCityDbPath || config.maxmindAsnDbPath) this.maxmindBackend = new MaxMindBackend({
31
+ cityDbPath: config.maxmindCityDbPath,
32
+ asnDbPath: config.maxmindAsnDbPath,
33
+ logger: config.logger
34
+ });
35
+ if (config.ipapiUrl) this.ipapiBackend = new IpapiBackend({
36
+ baseUrl: config.ipapiUrl,
37
+ apiKey: config.ipapiKey,
38
+ logger: config.logger
39
+ });
40
+ }
41
+ async initialize() {
42
+ if (this.maxmindBackend) await this.maxmindBackend.initialize();
43
+ this.config.logger?.info(() => ({
44
+ msg: "IpInfoService initialized",
45
+ data: {
46
+ maxmindAvailable: this.maxmindBackend?.isAvailable() ?? false,
47
+ ipapiAvailable: this.ipapiBackend?.isAvailable() ?? false
48
+ }
49
+ }));
50
+ }
51
+ isAvailable() {
52
+ return (this.maxmindBackend?.isAvailable() ?? false) || (this.ipapiBackend?.isAvailable() ?? false);
53
+ }
54
+ async lookup(ip) {
55
+ if (isNonRoutable(ip)) return {
56
+ isValid: false,
57
+ error: "Non-routable IP address",
58
+ ip
59
+ };
60
+ if (this.ipapiBackend?.isAvailable()) {
61
+ const result = await this.ipapiBackend.lookup(ip);
62
+ if (result.isValid) return result;
63
+ this.config.logger?.debug(() => ({
64
+ msg: "ipapi.is lookup failed, falling back to MaxMind",
65
+ data: {
66
+ ip,
67
+ error: "error" in result ? result.error : "unknown"
68
+ }
69
+ }));
70
+ if (this.maxmindBackend?.isAvailable()) return this.maxmindBackend.lookup(ip);
71
+ return result;
72
+ }
73
+ if (this.maxmindBackend?.isAvailable()) return this.maxmindBackend.lookup(ip);
74
+ return {
75
+ isValid: false,
76
+ error: "No IP info backend available",
77
+ ip
78
+ };
79
+ }
89
80
  };
81
+ //#endregion
82
+ export { IpInfoService, isNonRoutable };
@@ -1 +1 @@
1
- {"version":3,"file":"IpInfoService.js","sourceRoot":"","sources":["../src/IpInfoService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IpInfoService.js","sourceRoot":"","sources":["../src/IpInfoService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import "node:module";
2
+ //#endregion
3
+ export {};
@@ -1,14 +1,20 @@
1
1
  import type { Logger } from "@prosopo/logger";
2
2
  import type { IPInfoResponse } from "@prosopo/types";
3
+ export declare const DEFAULT_TIMEOUT_MS = 700;
4
+ export type FetchFn = (url: string, init: RequestInit) => Promise<globalThis.Response>;
3
5
  export interface IpapiBackendConfig {
4
6
  baseUrl: string;
5
7
  apiKey?: string;
6
8
  logger?: Logger;
9
+ fetch?: FetchFn;
10
+ timeoutMs?: number;
7
11
  }
12
+ export declare const parseAbuserScore: (score: string | undefined) => number | undefined;
8
13
  export declare class IpapiBackend {
9
14
  private config;
10
15
  constructor(config: IpapiBackendConfig);
11
16
  isAvailable(): boolean;
17
+ private get timeoutMs();
12
18
  lookup(ip: string): Promise<IPInfoResponse>;
13
19
  }
14
20
  //# sourceMappingURL=ipapi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ipapi.d.ts","sourceRoot":"","sources":["../../src/backends/ipapi.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAEX,cAAc,EAEd,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,YAAY;IACxB,OAAO,CAAC,MAAM,CAAqB;gBAEvB,MAAM,EAAE,kBAAkB;IAItC,WAAW,IAAI,OAAO;IAIhB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CA4GjD"}
1
+ {"version":3,"file":"ipapi.d.ts","sourceRoot":"","sources":["../../src/backends/ipapi.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAEX,cAAc,EAEd,MAAM,gBAAgB,CAAC;AAMxB,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAGtC,MAAM,MAAM,OAAO,GAAG,CACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,WAAW,KACb,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AAElC,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAuBD,eAAO,MAAM,gBAAgB,UACrB,MAAM,GAAG,SAAS,KACvB,MAAM,GAAG,SAOX,CAAC;AAEF,qBAAa,YAAY;IACxB,OAAO,CAAC,MAAM,CAAqB;gBAEvB,MAAM,EAAE,kBAAkB;IAItC,WAAW,IAAI,OAAO;IAItB,OAAO,KAAK,SAAS,GAEpB;IAEK,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAyGjD"}
@@ -1,105 +1,118 @@
1
- const TIMEOUT_MS = 700;
2
- class IpapiBackend {
3
- constructor(config) {
4
- this.config = config;
5
- }
6
- isAvailable() {
7
- return Boolean(this.config.baseUrl);
8
- }
9
- async lookup(ip) {
10
- try {
11
- if (!ip || typeof ip !== "string") {
12
- return {
13
- isValid: false,
14
- error: "Invalid IP address provided",
15
- ip: ip || "undefined"
16
- };
17
- }
18
- const body = { q: ip };
19
- if (this.config.apiKey) {
20
- body.key = this.config.apiKey;
21
- }
22
- const controller = new AbortController();
23
- const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
24
- try {
25
- const response = await fetch(this.config.baseUrl, {
26
- method: "POST",
27
- headers: {
28
- "Content-Type": "application/json",
29
- Accept: "application/json"
30
- },
31
- body: JSON.stringify(body),
32
- signal: controller.signal
33
- });
34
- clearTimeout(timeoutId);
35
- if (!response.ok) {
36
- return {
37
- isValid: false,
38
- error: `API request failed with status ${response.status}: ${response.statusText}`,
39
- ip
40
- };
41
- }
42
- const data = await response.json();
43
- if (data.is_bogon) {
44
- return {
45
- isValid: false,
46
- error: "IP address is bogon (non-routable)",
47
- ip
48
- };
49
- }
50
- const result = {
51
- ip: data.ip,
52
- isValid: true,
53
- isVPN: data.is_vpn,
54
- isTor: data.is_tor,
55
- isProxy: data.is_proxy,
56
- isDatacenter: data.is_datacenter,
57
- isAbuser: data.is_abuser,
58
- isMobile: data.is_mobile,
59
- isSatellite: data.is_satellite,
60
- isCrawler: data.is_crawler,
61
- providerName: data.company?.name || data.datacenter?.datacenter,
62
- providerType: data.company?.type || data.asn?.type,
63
- asnNumber: data.asn?.asn,
64
- asnOrganization: data.asn?.org,
65
- datacenterName: data.datacenter?.datacenter,
66
- country: data.location?.country,
67
- countryCode: data.location?.country_code,
68
- region: data.location?.state,
69
- city: data.location?.city,
70
- latitude: data.location?.latitude,
71
- longitude: data.location?.longitude,
72
- timezone: data.location?.timezone,
73
- vpnService: data.vpn?.service,
74
- vpnType: data.vpn?.type,
75
- abuserScore: Number.parseFloat(
76
- data.asn?.abuser_score.split(" ")[0] || "0"
77
- ),
78
- companyAbuserScore: Number.parseFloat(
79
- data.company?.abuser_score.split(" ")[0] || "0"
80
- )
81
- };
82
- return result;
83
- } catch (fetchError) {
84
- clearTimeout(timeoutId);
85
- if (fetchError instanceof Error && fetchError.name === "AbortError") {
86
- return {
87
- isValid: false,
88
- error: `Request timed out after ${TIMEOUT_MS}ms`,
89
- ip
90
- };
91
- }
92
- throw fetchError;
93
- }
94
- } catch (error) {
95
- return {
96
- isValid: false,
97
- error: `Network or parsing error: ${error instanceof Error ? error.message : String(error)}`,
98
- ip
99
- };
100
- }
101
- }
102
- }
103
- export {
104
- IpapiBackend
1
+ /**
2
+ * Parse an upstream abuser score, which arrives as a string like "0.0012 (Low)".
3
+ *
4
+ * The field is declared required by the response type but is not guaranteed by
5
+ * the wire: it comes from `response.json()`, which is cast, not validated. A
6
+ * missing value used to throw, and the throw was caught far above as a generic
7
+ * "Network or parsing error" — discarding an otherwise complete and successful
8
+ * lookup over one absent score.
9
+ *
10
+ * Returns `undefined` — not 0 — when the field is absent or unparseable. The
11
+ * scale is 0..1 with 0 meaning "clean" (see `abuserScoreThreshold`, declared
12
+ * `{min: 0, max: 1}`), so a literal 0 would assert cleanliness we have not
13
+ * established. `undefined` says "unknown" instead, and the one consumer
14
+ * (checkTrafficFilter) already resolves it with `?? 0`, so the effective
15
+ * blocking behaviour is unchanged while the distinction stays available.
16
+ *
17
+ * Fail-closed alternatives were rejected: 1 turns any upstream formatting
18
+ * change into a silent max-severity block indistinguishable from a genuine
19
+ * 1.0, and throwing reintroduces exactly the bug above — a cosmetic sub-field
20
+ * collapsing a good lookup into a total failure.
21
+ */
22
+ var parseAbuserScore = (score) => {
23
+ const head = score?.split(" ")[0];
24
+ if (!head) return;
25
+ const parsed = Number.parseFloat(head);
26
+ return Number.isNaN(parsed) ? void 0 : parsed;
105
27
  };
28
+ var IpapiBackend = class {
29
+ constructor(config) {
30
+ this.config = config;
31
+ }
32
+ isAvailable() {
33
+ return Boolean(this.config.baseUrl);
34
+ }
35
+ get timeoutMs() {
36
+ return this.config.timeoutMs ?? 700;
37
+ }
38
+ async lookup(ip) {
39
+ try {
40
+ if (!ip || typeof ip !== "string") return {
41
+ isValid: false,
42
+ error: "Invalid IP address provided",
43
+ ip: ip || "undefined"
44
+ };
45
+ const body = { q: ip };
46
+ if (this.config.apiKey) body.key = this.config.apiKey;
47
+ const controller = new AbortController();
48
+ const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
49
+ try {
50
+ const response = await (this.config.fetch ?? globalThis.fetch)(this.config.baseUrl, {
51
+ method: "POST",
52
+ headers: {
53
+ "Content-Type": "application/json",
54
+ Accept: "application/json"
55
+ },
56
+ body: JSON.stringify(body),
57
+ signal: controller.signal
58
+ });
59
+ clearTimeout(timeoutId);
60
+ if (!response.ok) return {
61
+ isValid: false,
62
+ error: `API request failed with status ${response.status}: ${response.statusText}`,
63
+ ip
64
+ };
65
+ const data = await response.json();
66
+ if (data.is_bogon) return {
67
+ isValid: false,
68
+ error: "IP address is bogon (non-routable)",
69
+ ip
70
+ };
71
+ return {
72
+ ip: data.ip,
73
+ isValid: true,
74
+ isVPN: data.is_vpn,
75
+ isTor: data.is_tor,
76
+ isProxy: data.is_proxy,
77
+ isDatacenter: data.is_datacenter,
78
+ isAbuser: data.is_abuser,
79
+ isMobile: data.is_mobile,
80
+ isSatellite: data.is_satellite,
81
+ isCrawler: data.is_crawler,
82
+ providerName: data.company?.name || data.datacenter?.datacenter,
83
+ providerType: data.company?.type || data.asn?.type,
84
+ asnNumber: data.asn?.asn,
85
+ asnOrganization: data.asn?.org,
86
+ datacenterName: data.datacenter?.datacenter,
87
+ country: data.location?.country,
88
+ countryCode: data.location?.country_code,
89
+ region: data.location?.state,
90
+ city: data.location?.city,
91
+ latitude: data.location?.latitude,
92
+ longitude: data.location?.longitude,
93
+ timezone: data.location?.timezone,
94
+ vpnService: data.vpn?.service,
95
+ vpnType: data.vpn?.type,
96
+ abuserScore: parseAbuserScore(data.asn?.abuser_score),
97
+ companyAbuserScore: parseAbuserScore(data.company?.abuser_score)
98
+ };
99
+ } catch (fetchError) {
100
+ clearTimeout(timeoutId);
101
+ if (fetchError instanceof Error && fetchError.name === "AbortError") return {
102
+ isValid: false,
103
+ error: `Request timed out after ${this.timeoutMs}ms`,
104
+ ip
105
+ };
106
+ throw fetchError;
107
+ }
108
+ } catch (error) {
109
+ return {
110
+ isValid: false,
111
+ error: `Network or parsing error: ${error instanceof Error ? error.message : String(error)}`,
112
+ ip
113
+ };
114
+ }
115
+ }
116
+ };
117
+ //#endregion
118
+ export { IpapiBackend, parseAbuserScore };
@@ -1 +1 @@
1
- {"version":3,"file":"ipapi.js","sourceRoot":"","sources":["../../src/backends/ipapi.ts"],"names":[],"mappings":"AAqBA,MAAM,UAAU,GAAG,GAAG,CAAC;AAQvB,MAAM,OAAO,YAAY;IAGxB,YAAY,MAA0B;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAED,WAAW;QACV,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACtB,IAAI,CAAC;YACJ,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;gBACnC,OAAO;oBACN,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,6BAA6B;oBACpC,EAAE,EAAE,EAAE,IAAI,WAAW;iBACrB,CAAC;YACH,CAAC;YAED,MAAM,IAAI,GAAgC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;YACpD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACxB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YAC/B,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;YAEnE,IAAI,CAAC;gBACJ,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;oBACjD,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACR,cAAc,EAAE,kBAAkB;wBAClC,MAAM,EAAE,kBAAkB;qBAC1B;oBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;oBAC1B,MAAM,EAAE,UAAU,CAAC,MAAM;iBACzB,CAAC,CAAC;gBAEH,YAAY,CAAC,SAAS,CAAC,CAAC;gBAExB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBAClB,OAAO;wBACN,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,kCAAkC,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE;wBAClF,EAAE;qBACF,CAAC;gBACH,CAAC;gBAED,MAAM,IAAI,GAAkB,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkB,CAAC;gBAErE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACnB,OAAO;wBACN,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,oCAAoC;wBAC3C,EAAE;qBACF,CAAC;gBACH,CAAC;gBAED,MAAM,MAAM,GAAiB;oBAC5B,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,OAAO,EAAE,IAAI;oBAEb,KAAK,EAAE,IAAI,CAAC,MAAM;oBAClB,KAAK,EAAE,IAAI,CAAC,MAAM;oBAClB,OAAO,EAAE,IAAI,CAAC,QAAQ;oBACtB,YAAY,EAAE,IAAI,CAAC,aAAa;oBAChC,QAAQ,EAAE,IAAI,CAAC,SAAS;oBACxB,QAAQ,EAAE,IAAI,CAAC,SAAS;oBACxB,WAAW,EAAE,IAAI,CAAC,YAAY;oBAC9B,SAAS,EAAE,IAAI,CAAC,UAAU;oBAC1B,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,UAAU;oBAC/D,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI;oBAClD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG;oBACxB,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG;oBAC9B,cAAc,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU;oBAE3C,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO;oBAC/B,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,YAAY;oBACxC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK;oBAC5B,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI;oBACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ;oBACjC,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS;oBACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ;oBAEjC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO;oBAC7B,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI;oBAEvB,WAAW,EAAE,MAAM,CAAC,UAAU,CAC7B,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAC3C;oBACD,kBAAkB,EAAE,MAAM,CAAC,UAAU,CACpC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAC/C;iBACD,CAAC;gBAEF,OAAO,MAAM,CAAC;YACf,CAAC;YAAC,OAAO,UAAU,EAAE,CAAC;gBACrB,YAAY,CAAC,SAAS,CAAC,CAAC;gBAExB,IAAI,UAAU,YAAY,KAAK,IAAI,UAAU,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACrE,OAAO;wBACN,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,2BAA2B,UAAU,IAAI;wBAChD,EAAE;qBACF,CAAC;gBACH,CAAC;gBAED,MAAM,UAAU,CAAC;YAClB,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,6BAA6B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;gBAC5F,EAAE;aACF,CAAC;QACH,CAAC;IACF,CAAC;CACD"}
1
+ {"version":3,"file":"ipapi.js","sourceRoot":"","sources":["../../src/backends/ipapi.ts"],"names":[],"mappings":"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"}