@prosopo/ipinfo 0.2.14

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.
@@ -0,0 +1,27 @@
1
+
2
+ > @prosopo/ipinfo@0.2.10 build:tsc
3
+ > tsc --build --verbose
4
+
5
+ 17:33:58 - Projects in this build:
6
+ * ../../dev/config/tsconfig.json
7
+ * ../locale/tsconfig.json
8
+ * ../util/tsconfig.json
9
+ * ../util-crypto/tsconfig.json
10
+ * ../types/tsconfig.json
11
+ * ../common/tsconfig.json
12
+ * tsconfig.json
13
+
14
+ 17:33:58 - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/vite/vite.backend.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
15
+
16
+ 17:33:58 - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/locales/tr/translation.json' is older than output '../locale/tsconfig.tsbuildinfo'
17
+
18
+ 17:33:58 - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
19
+
20
+ 17:33:58 - 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'
21
+
22
+ 17:33:58 - Project '../types/tsconfig.json' is up to date because newest input '../types/src/provider/database.ts' is older than output '../types/tsconfig.tsbuildinfo'
23
+
24
+ 17:33:58 - Project '../common/tsconfig.json' is up to date because newest input '../common/src/error.ts' is older than output '../common/tsconfig.tsbuildinfo'
25
+
26
+ 17:33:58 - Project 'tsconfig.json' is up to date because newest input 'src/IpInfoService.ts' is older than output 'tsconfig.tsbuildinfo'
27
+
@@ -0,0 +1,38 @@
1
+
2
+
3
+ > @prosopo/ipinfo@0.2.11 build
4
+ > npm run build:cross-env -- --mode ${NODE_ENV:-development}
5
+
6
+
7
+ > @prosopo/ipinfo@0.2.11 build:cross-env
8
+ > vite build --config vite.esm.config.ts --mode production
9
+
10
+ ViteEsmConfig: .
11
+ {
12
+ tsConfigPaths: [
13
+ '/home/chris/dev/prosopo/captcha-private2/captcha/packages/logger/tsconfig.json',
14
+ '/home/chris/dev/prosopo/captcha-private2/captcha/packages/types/tsconfig.json',
15
+ '/home/chris/dev/prosopo/captcha-private2/captcha/packages/locale/tsconfig.json',
16
+ '/home/chris/dev/prosopo/captcha-private2/captcha/packages/util/tsconfig.json',
17
+ '/home/chris/dev/prosopo/captcha-private2/captcha/packages/util-crypto/tsconfig.json'
18
+ ]
19
+ }
20
+ {
21
+ externals: [
22
+ '@prosopo/logger',
23
+ '@prosopo/types',
24
+ '@prosopo/locale',
25
+ '@prosopo/util',
26
+ '@prosopo/util-crypto'
27
+ ]
28
+ }
29
+ vite v6.4.1 building SSR bundle for production...
30
+ Bundle build started
31
+ transforming (1) src/index.tsBuild end
32
+ ✓ 4 modules transformed.
33
+ rendering chunks (1)...rendering chunks (2)...rendering chunks (3)...rendering chunks (4)...dist/index.js 0.08 kB
34
+ dist/IpInfoService.js 2.67 kB
35
+ dist/backends/ipapi.js 3.14 kB
36
+ dist/backends/maxmind.js 4.44 kB
37
+ ✓ built in 142ms
38
+ ⠙⠙
@@ -0,0 +1,4 @@
1
+
2
+ > @prosopo/ipinfo@0.2.4 typecheck
3
+ > tsc --project tsconfig.types.json
4
+
package/CHANGELOG.md ADDED
@@ -0,0 +1,119 @@
1
+ # @prosopo/ipinfo
2
+
3
+ ## 0.2.14
4
+ ### Patch Changes
5
+
6
+ - Updated dependencies [a1d60db]
7
+ - Updated dependencies [2392aaf]
8
+ - Updated dependencies [97cf7bd]
9
+ - Updated dependencies [6ca1125]
10
+ - Updated dependencies [32a591b]
11
+ - @prosopo/types@4.3.0
12
+ - @prosopo/logger@1.0.2
13
+
14
+ ## 0.2.13
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies [6c26669]
18
+ - Updated dependencies [f7f9ec5]
19
+ - @prosopo/types@4.2.1
20
+
21
+ ## 0.2.12
22
+ ### Patch Changes
23
+
24
+ - 0fd81af: Extract the logger into its own `@prosopo/logger` package, out of `@prosopo/common`. Consumers now import logger symbols from `@prosopo/logger`; `@prosopo/common` no longer re-exports them. Unused `@prosopo/common` dependencies pruned where the only usage was the logger.
25
+ - Updated dependencies [0fd81af]
26
+ - @prosopo/logger@1.0.1
27
+
28
+ ## 0.2.11
29
+ ### Patch Changes
30
+
31
+ - Updated dependencies [20cae63]
32
+ - Updated dependencies [4d9923e]
33
+ - @prosopo/types@4.2.0
34
+
35
+ ## 0.2.10
36
+ ### Patch Changes
37
+
38
+ - Updated dependencies [d351362]
39
+ - @prosopo/types@4.1.4
40
+
41
+ ## 0.2.9
42
+ ### Patch Changes
43
+
44
+ - Updated dependencies [e2711ae]
45
+ - Updated dependencies [5786629]
46
+ - @prosopo/types@4.1.3
47
+ - @prosopo/common@3.1.36
48
+
49
+ ## 0.2.8
50
+ ### Patch Changes
51
+
52
+ - @prosopo/types@4.1.2
53
+
54
+ ## 0.2.7
55
+ ### Patch Changes
56
+
57
+ - Updated dependencies [91958da]
58
+ - @prosopo/types@4.1.1
59
+ - @prosopo/common@3.1.35
60
+
61
+ ## 0.2.6
62
+ ### Patch Changes
63
+
64
+ - Updated dependencies [6a741ce]
65
+ - @prosopo/types@4.1.0
66
+
67
+ ## 0.2.5
68
+ ### Patch Changes
69
+
70
+ - Updated dependencies [3c0be68]
71
+ - Updated dependencies [f9ea09d]
72
+ - Updated dependencies [d865319]
73
+ - Updated dependencies [753304b]
74
+ - Updated dependencies [8bb7286]
75
+ - Updated dependencies [f9ea09d]
76
+ - Updated dependencies [4aae4e6]
77
+ - Updated dependencies [4993813]
78
+ - @prosopo/types@4.0.0
79
+ - @prosopo/common@3.1.34
80
+
81
+ ## 0.2.4
82
+ ### Patch Changes
83
+
84
+ - Updated dependencies [819ed95]
85
+ - @prosopo/types@3.16.1
86
+
87
+ ## 0.2.3
88
+ ### Patch Changes
89
+
90
+ - Updated dependencies [f6a4402]
91
+ - Updated dependencies [99dfb44]
92
+ - @prosopo/types@3.16.0
93
+
94
+ ## 0.2.2
95
+ ### Patch Changes
96
+
97
+ - Updated dependencies [3e54c0a]
98
+ - @prosopo/types@3.15.0
99
+
100
+ ## 0.2.1
101
+ ### Patch Changes
102
+
103
+ - Updated dependencies [946a8ba]
104
+ - Updated dependencies [5614814]
105
+ - @prosopo/types@3.14.1
106
+ - @prosopo/common@3.1.33
107
+
108
+ ## 0.2.0
109
+ ### Minor Changes
110
+
111
+ - 42650db: Add better spam rules and move ipinfo service to local instead of external
112
+
113
+ ### Patch Changes
114
+
115
+ - fc514dd: ability to block different types of traffic
116
+ - Updated dependencies [fc514dd]
117
+ - Updated dependencies [42650db]
118
+ - @prosopo/types@3.14.0
119
+ - @prosopo/common@3.1.32
@@ -0,0 +1,12 @@
1
+ import type { IPInfoResponse } from "@prosopo/types";
2
+ import type { IIpInfoService, IpInfoServiceConfig } from "./types.js";
3
+ export declare class IpInfoService implements IIpInfoService {
4
+ private maxmindBackend;
5
+ private ipapiBackend;
6
+ private config;
7
+ constructor(config: IpInfoServiceConfig);
8
+ initialize(): Promise<void>;
9
+ isAvailable(): boolean;
10
+ lookup(ip: string): Promise<IPInfoResponse>;
11
+ }
12
+ //# sourceMappingURL=IpInfoService.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,96 @@
1
+ import { IpapiBackend } from "./backends/ipapi.js";
2
+ import { MaxMindBackend } from "./backends/maxmind.js";
3
+ function isNonRoutable(ip) {
4
+ const normalized = ip.replace(/^::ffff:/i, "");
5
+ if (normalized.startsWith("127.") ||
6
+ normalized.startsWith("10.") ||
7
+ normalized.startsWith("192.168.") ||
8
+ normalized.startsWith("169.254.") ||
9
+ normalized === "0.0.0.0") {
10
+ return true;
11
+ }
12
+ if (normalized.startsWith("172.")) {
13
+ const second = Number.parseInt(normalized.split(".")[1] ?? "", 10);
14
+ if (second >= 16 && second <= 31)
15
+ return true;
16
+ }
17
+ if (normalized === "::1" || normalized === "::")
18
+ return true;
19
+ if (/^f[cd]/i.test(normalized))
20
+ return true;
21
+ if (/^fe[89ab]/i.test(normalized))
22
+ return true;
23
+ return false;
24
+ }
25
+ export class IpInfoService {
26
+ constructor(config) {
27
+ this.maxmindBackend = null;
28
+ this.ipapiBackend = null;
29
+ this.config = config;
30
+ if (config.maxmindCityDbPath || config.maxmindAsnDbPath) {
31
+ this.maxmindBackend = new MaxMindBackend({
32
+ cityDbPath: config.maxmindCityDbPath,
33
+ asnDbPath: config.maxmindAsnDbPath,
34
+ logger: config.logger,
35
+ });
36
+ }
37
+ if (config.ipapiUrl) {
38
+ this.ipapiBackend = new IpapiBackend({
39
+ baseUrl: config.ipapiUrl,
40
+ apiKey: config.ipapiKey,
41
+ logger: config.logger,
42
+ });
43
+ }
44
+ }
45
+ async initialize() {
46
+ if (this.maxmindBackend) {
47
+ await this.maxmindBackend.initialize();
48
+ }
49
+ this.config.logger?.info(() => ({
50
+ msg: "IpInfoService initialized",
51
+ data: {
52
+ maxmindAvailable: this.maxmindBackend?.isAvailable() ?? false,
53
+ ipapiAvailable: this.ipapiBackend?.isAvailable() ?? false,
54
+ },
55
+ }));
56
+ }
57
+ isAvailable() {
58
+ return ((this.maxmindBackend?.isAvailable() ?? false) ||
59
+ (this.ipapiBackend?.isAvailable() ?? false));
60
+ }
61
+ async lookup(ip) {
62
+ if (isNonRoutable(ip)) {
63
+ return {
64
+ isValid: false,
65
+ error: "Non-routable IP address",
66
+ ip,
67
+ };
68
+ }
69
+ if (this.ipapiBackend?.isAvailable()) {
70
+ const result = await this.ipapiBackend.lookup(ip);
71
+ if (result.isValid) {
72
+ return result;
73
+ }
74
+ this.config.logger?.debug(() => ({
75
+ msg: "ipapi.is lookup failed, falling back to MaxMind",
76
+ data: {
77
+ ip,
78
+ error: "error" in result ? result.error : "unknown",
79
+ },
80
+ }));
81
+ if (this.maxmindBackend?.isAvailable()) {
82
+ return this.maxmindBackend.lookup(ip);
83
+ }
84
+ return result;
85
+ }
86
+ if (this.maxmindBackend?.isAvailable()) {
87
+ return this.maxmindBackend.lookup(ip);
88
+ }
89
+ return {
90
+ isValid: false,
91
+ error: "No IP info backend available",
92
+ ip,
93
+ };
94
+ }
95
+ }
96
+ //# sourceMappingURL=IpInfoService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IpInfoService.js","sourceRoot":"","sources":["../src/IpInfoService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Logger } from "@prosopo/logger";
2
+ import type { IPInfoResponse } from "@prosopo/types";
3
+ export interface IpapiBackendConfig {
4
+ baseUrl: string;
5
+ apiKey?: string;
6
+ logger?: Logger;
7
+ }
8
+ export declare class IpapiBackend {
9
+ private config;
10
+ constructor(config: IpapiBackendConfig);
11
+ isAvailable(): boolean;
12
+ lookup(ip: string): Promise<IPInfoResponse>;
13
+ }
14
+ //# sourceMappingURL=ipapi.d.ts.map
@@ -0,0 +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;CA2GjD"}
@@ -0,0 +1,100 @@
1
+ const TIMEOUT_MS = 700;
2
+ export 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
+ country: data.location?.country,
66
+ countryCode: data.location?.country_code,
67
+ region: data.location?.state,
68
+ city: data.location?.city,
69
+ latitude: data.location?.latitude,
70
+ longitude: data.location?.longitude,
71
+ timezone: data.location?.timezone,
72
+ vpnService: data.vpn?.service,
73
+ vpnType: data.vpn?.type,
74
+ abuserScore: Number.parseFloat(data.asn?.abuser_score.split(" ")[0] || "0"),
75
+ companyAbuserScore: Number.parseFloat(data.company?.abuser_score.split(" ")[0] || "0"),
76
+ };
77
+ return result;
78
+ }
79
+ catch (fetchError) {
80
+ clearTimeout(timeoutId);
81
+ if (fetchError instanceof Error && fetchError.name === "AbortError") {
82
+ return {
83
+ isValid: false,
84
+ error: `Request timed out after ${TIMEOUT_MS}ms`,
85
+ ip,
86
+ };
87
+ }
88
+ throw fetchError;
89
+ }
90
+ }
91
+ catch (error) {
92
+ return {
93
+ isValid: false,
94
+ error: `Network or parsing error: ${error instanceof Error ? error.message : String(error)}`,
95
+ ip,
96
+ };
97
+ }
98
+ }
99
+ }
100
+ //# sourceMappingURL=ipapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipapi.js","sourceRoot":"","sources":["../../src/backends/ipapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Logger } from "@prosopo/logger";
2
+ import type { IPInfoResponse } from "@prosopo/types";
3
+ export interface MaxMindBackendConfig {
4
+ cityDbPath?: string;
5
+ asnDbPath?: string;
6
+ logger?: Logger;
7
+ }
8
+ export declare class MaxMindBackend {
9
+ private cityReader;
10
+ private asnReader;
11
+ private config;
12
+ constructor(config: MaxMindBackendConfig);
13
+ initialize(): Promise<void>;
14
+ isAvailable(): boolean;
15
+ lookup(ip: string): Promise<IPInfoResponse>;
16
+ }
17
+ //# sourceMappingURL=maxmind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maxmind.d.ts","sourceRoot":"","sources":["../../src/backends/maxmind.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,gBAAgB,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,cAAc;IAC1B,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,MAAM,CAAuB;gBAEzB,MAAM,EAAE,oBAAoB;IAIlC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCjC,WAAW,IAAI,OAAO;IAIhB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CA8FjD"}
@@ -0,0 +1,150 @@
1
+ export class MaxMindBackend {
2
+ constructor(config) {
3
+ this.cityReader = null;
4
+ this.asnReader = null;
5
+ this.config = config;
6
+ }
7
+ async initialize() {
8
+ const { Reader } = await import("@maxmind/geoip2-node");
9
+ if (this.config.cityDbPath) {
10
+ try {
11
+ this.cityReader = await Reader.open(this.config.cityDbPath);
12
+ this.config.logger?.info(() => ({
13
+ msg: "MaxMind City reader initialized",
14
+ data: { dbPath: this.config.cityDbPath },
15
+ }));
16
+ }
17
+ catch (error) {
18
+ this.config.logger?.warn(() => ({
19
+ msg: "Failed to initialize MaxMind City reader",
20
+ err: error,
21
+ data: { dbPath: this.config.cityDbPath },
22
+ }));
23
+ }
24
+ }
25
+ if (this.config.asnDbPath) {
26
+ try {
27
+ this.asnReader = await Reader.open(this.config.asnDbPath);
28
+ this.config.logger?.info(() => ({
29
+ msg: "MaxMind ASN reader initialized",
30
+ data: { dbPath: this.config.asnDbPath },
31
+ }));
32
+ }
33
+ catch (error) {
34
+ this.config.logger?.warn(() => ({
35
+ msg: "Failed to initialize MaxMind ASN reader",
36
+ err: error,
37
+ data: { dbPath: this.config.asnDbPath },
38
+ }));
39
+ }
40
+ }
41
+ }
42
+ isAvailable() {
43
+ return this.cityReader !== null || this.asnReader !== null;
44
+ }
45
+ async lookup(ip) {
46
+ if (!this.isAvailable()) {
47
+ return {
48
+ isValid: false,
49
+ error: "MaxMind readers not initialized",
50
+ ip,
51
+ };
52
+ }
53
+ try {
54
+ let cityData;
55
+ let asnData;
56
+ if (this.cityReader) {
57
+ try {
58
+ cityData = this.cityReader.city(ip);
59
+ }
60
+ catch (error) {
61
+ this.config.logger?.debug(() => ({
62
+ msg: "MaxMind City lookup failed",
63
+ data: { ip },
64
+ err: error,
65
+ }));
66
+ }
67
+ }
68
+ if (this.asnReader) {
69
+ try {
70
+ asnData = this.asnReader.asn(ip);
71
+ }
72
+ catch (error) {
73
+ this.config.logger?.debug(() => ({
74
+ msg: "MaxMind ASN lookup failed",
75
+ data: { ip },
76
+ err: error,
77
+ }));
78
+ }
79
+ }
80
+ if (!cityData && !asnData) {
81
+ return {
82
+ isValid: false,
83
+ error: "No MaxMind data available for IP",
84
+ ip,
85
+ };
86
+ }
87
+ const result = {
88
+ ip,
89
+ isValid: true,
90
+ isVPN: cityData?.traits?.isAnonymousVpn ?? false,
91
+ isTor: cityData?.traits?.isTorExitNode ?? false,
92
+ isProxy: (cityData?.traits?.isPublicProxy ?? false) ||
93
+ (cityData?.traits?.isResidentialProxy ?? false),
94
+ isDatacenter: cityData?.traits?.isHostingProvider ?? false,
95
+ isAbuser: false,
96
+ isMobile: false,
97
+ isSatellite: cityData?.traits?.isSatelliteProvider ?? false,
98
+ isCrawler: false,
99
+ country: cityData?.country?.names?.en,
100
+ countryCode: cityData?.country?.isoCode,
101
+ region: cityData?.subdivisions?.[0]?.names?.en,
102
+ city: cityData?.city?.names?.en,
103
+ latitude: cityData?.location?.latitude,
104
+ longitude: cityData?.location?.longitude,
105
+ timezone: cityData?.location?.timeZone,
106
+ asnNumber: cityData?.traits?.autonomousSystemNumber ??
107
+ asnData?.autonomousSystemNumber,
108
+ asnOrganization: cityData?.traits?.autonomousSystemOrganization ??
109
+ asnData?.autonomousSystemOrganization,
110
+ providerName: cityData?.traits?.autonomousSystemOrganization ??
111
+ asnData?.autonomousSystemOrganization,
112
+ providerType: mapUserType(cityData?.traits?.userType),
113
+ };
114
+ return result;
115
+ }
116
+ catch (error) {
117
+ return {
118
+ isValid: false,
119
+ error: `MaxMind lookup error: ${error instanceof Error ? error.message : String(error)}`,
120
+ ip,
121
+ };
122
+ }
123
+ }
124
+ }
125
+ function mapUserType(userType) {
126
+ switch (userType) {
127
+ case "hosting":
128
+ case "content_delivery_network":
129
+ return "hosting";
130
+ case "college":
131
+ case "school":
132
+ case "library":
133
+ return "education";
134
+ case "government":
135
+ case "military":
136
+ return "government";
137
+ case "business":
138
+ return "business";
139
+ case "residential":
140
+ case "cellular":
141
+ case "dialup":
142
+ case "cafe":
143
+ case "traveler":
144
+ case "router":
145
+ return "isp";
146
+ default:
147
+ return undefined;
148
+ }
149
+ }
150
+ //# sourceMappingURL=maxmind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maxmind.js","sourceRoot":"","sources":["../../src/backends/maxmind.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { IpInfoService } from "./IpInfoService.js";
2
+ export type { IIpInfoService, IpInfoServiceConfig } from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { IpInfoService } from "./IpInfoService.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Logger } from "@prosopo/logger";
2
+ import type { IPInfoResponse } from "@prosopo/types";
3
+ export interface IIpInfoService {
4
+ initialize(): Promise<void>;
5
+ lookup(ip: string): Promise<IPInfoResponse>;
6
+ isAvailable(): boolean;
7
+ }
8
+ export interface IpInfoServiceConfig {
9
+ maxmindCityDbPath?: string;
10
+ maxmindAsnDbPath?: string;
11
+ ipapiUrl?: string;
12
+ ipapiKey?: string;
13
+ logger?: Logger;
14
+ }
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC9B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5C,WAAW,IAAI,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@prosopo/ipinfo",
3
+ "version": "0.2.14",
4
+ "description": "IP information service with MaxMind and ipapi.is backends",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "engines": {
9
+ "node": "^24",
10
+ "npm": "^11"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/cjs/index.cjs"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "clean": "del-cli --verbose dist tsconfig.tsbuildinfo",
21
+ "build": "npm run build:cross-env -- --mode ${NODE_ENV:-development}",
22
+ "build:cross-env": "vite build --config vite.esm.config.ts",
23
+ "build:tsc": "tsc --build --verbose",
24
+ "build:cjs": "NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV",
25
+ "typecheck": "tsc --project tsconfig.types.json"
26
+ },
27
+ "dependencies": {
28
+ "@maxmind/geoip2-node": "5.0.0",
29
+ "@prosopo/logger": "1.0.2",
30
+ "@prosopo/types": "4.3.0"
31
+ },
32
+ "devDependencies": {
33
+ "@prosopo/config": "3.3.1",
34
+ "@types/node": "22.10.2",
35
+ "@vitest/coverage-v8": "3.2.4",
36
+ "del-cli": "6.0.0",
37
+ "tslib": "2.7.0",
38
+ "typescript": "5.6.2",
39
+ "vite": "6.4.1",
40
+ "vitest": "3.2.4"
41
+ },
42
+ "license": "Apache-2.0",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/prosopo/captcha.git",
46
+ "directory": "packages/ipinfo"
47
+ }
48
+ }
@@ -0,0 +1,22 @@
1
+ import path from "node:path";
2
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ import { ViteCommonJSConfig } from "@prosopo/config";
16
+
17
+ export default function () {
18
+ return ViteCommonJSConfig(
19
+ path.basename("."),
20
+ path.resolve("./tsconfig.json"),
21
+ );
22
+ }
@@ -0,0 +1,20 @@
1
+ // Copyright 2021-2026 Prosopo (UK) Ltd.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import path from "node:path";
16
+ import { ViteEsmConfig } from "@prosopo/config";
17
+
18
+ export default function () {
19
+ return ViteEsmConfig(path.basename("."), path.resolve("./tsconfig.json"));
20
+ }