@artsnoa/ipc-sdk 1.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 +55 -0
- package/README.md +325 -0
- package/dist/index.d.mts +174 -0
- package/dist/index.d.ts +174 -0
- package/dist/index.js +283 -0
- package/dist/index.mjs +255 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Artsnoa.com(mirseo)
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
This software and associated documentation files (the "Software") are the proprietary
|
|
8
|
+
and confidential information of Artsnoa.com(mirseo). The Software is licensed, not sold.
|
|
9
|
+
|
|
10
|
+
NOTICE TO USER: This Software is protected by copyright laws and international copyright
|
|
11
|
+
treaties, as well as other intellectual property laws and treaties. The Software is
|
|
12
|
+
licensed, not sold.
|
|
13
|
+
|
|
14
|
+
PERMITTED USE:
|
|
15
|
+
|
|
16
|
+
You may use this Software in accordance with the terms and conditions specified at
|
|
17
|
+
https://ipc.artsnoa.com. Usage rights are granted as defined in the IPC service terms
|
|
18
|
+
and conditions.
|
|
19
|
+
|
|
20
|
+
RESTRICTIONS:
|
|
21
|
+
|
|
22
|
+
1. You may NOT modify, alter, adapt, or create derivative works of the Software.
|
|
23
|
+
|
|
24
|
+
2. You may NOT reverse engineer, decompile, or disassemble the Software, except and
|
|
25
|
+
only to the extent that such activity is expressly permitted by applicable law
|
|
26
|
+
notwithstanding this limitation.
|
|
27
|
+
|
|
28
|
+
3. You may NOT remove, alter, or obscure any copyright, trademark, or other proprietary
|
|
29
|
+
rights notices contained in or on the Software.
|
|
30
|
+
|
|
31
|
+
4. You may NOT redistribute, sublicense, rent, lease, or lend the Software in modified
|
|
32
|
+
form.
|
|
33
|
+
|
|
34
|
+
5. Any modifications, alterations, or tampering with the Software code is strictly
|
|
35
|
+
prohibited.
|
|
36
|
+
|
|
37
|
+
DISCLAIMER:
|
|
38
|
+
|
|
39
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
40
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
41
|
+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
42
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
43
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
44
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
45
|
+
|
|
46
|
+
TERMINATION:
|
|
47
|
+
|
|
48
|
+
This license is effective until terminated. Your rights under this license will
|
|
49
|
+
terminate automatically without notice if you fail to comply with any of its terms.
|
|
50
|
+
|
|
51
|
+
FOR LICENSING INQUIRIES:
|
|
52
|
+
|
|
53
|
+
For information regarding licensing of this Software, please contact:
|
|
54
|
+
Email: aurora@artsnoa.com
|
|
55
|
+
Website: https://ipc.artsnoa.com
|
package/README.md
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# IPC Artsnoa JavaScript SDK
|
|
2
|
+
|
|
3
|
+
Official JavaScript/TypeScript SDK for [ipc.artsnoa.com](https://ipc.artsnoa.com) API - Get your IP address and location information.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Full TypeScript support with type definitions
|
|
8
|
+
- Simple and intuitive API
|
|
9
|
+
- Comprehensive error handling
|
|
10
|
+
- Works in Node.js environments
|
|
11
|
+
- Minimal dependencies
|
|
12
|
+
- ESM and CommonJS support
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @artsnoa/ipc-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or with pnpm:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm add @artsnoa/ipc-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or with yarn:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
yarn add @artsnoa/ipc-sdk
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
import { IPCClient } from '@artsnoa/ipc-sdk';
|
|
36
|
+
|
|
37
|
+
// Initialize client (API key is optional)
|
|
38
|
+
const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
39
|
+
|
|
40
|
+
// Get detailed IP information
|
|
41
|
+
const details = await client.getIPDetails();
|
|
42
|
+
console.log(`Your IP: ${details.ip}, Country: ${details.country}`);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage Examples
|
|
46
|
+
|
|
47
|
+
### Basic Usage
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
import { IPCClient } from '@artsnoa/ipc-sdk';
|
|
51
|
+
|
|
52
|
+
// Create client with API key
|
|
53
|
+
const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
54
|
+
|
|
55
|
+
// Get IP details
|
|
56
|
+
const data = await client.getIPDetails();
|
|
57
|
+
console.log(`IP: ${data.ip}`);
|
|
58
|
+
console.log(`Country: ${data.country}`);
|
|
59
|
+
|
|
60
|
+
// Without API key
|
|
61
|
+
const publicClient = new IPCClient();
|
|
62
|
+
const publicData = await publicClient.getIPDetails();
|
|
63
|
+
console.log(`Your IP: ${publicData.ip}`);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### TypeScript Usage
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { IPCClient, IPDetailsResponse } from '@artsnoa/ipc-sdk';
|
|
70
|
+
|
|
71
|
+
const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
72
|
+
|
|
73
|
+
// Type-safe IP details
|
|
74
|
+
const details: IPDetailsResponse = await client.getIPDetails();
|
|
75
|
+
console.log(`IP: ${details.ip}`);
|
|
76
|
+
console.log(`User Agent: ${details.userAgent}`);
|
|
77
|
+
console.log(`ASN: ${details.asn}`);
|
|
78
|
+
console.log(`Country: ${details.country}`);
|
|
79
|
+
console.log(`Currency: ${details.currency}`);
|
|
80
|
+
console.log(`Languages: ${details.languages.join(', ')}`);
|
|
81
|
+
console.log(`Timestamp: ${details.timestamp}`);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### SDK Version Information
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
import { IPCClient } from '@artsnoa/ipc-sdk';
|
|
88
|
+
|
|
89
|
+
const client = new IPCClient();
|
|
90
|
+
|
|
91
|
+
// Get available SDK versions
|
|
92
|
+
const versions = await client.getSDKVersions();
|
|
93
|
+
console.log(`JavaScript SDK: ${versions.javascript}`);
|
|
94
|
+
console.log(`Python SDK: ${versions.python}`);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Custom Configuration
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
import { IPCClient } from '@artsnoa/ipc-sdk';
|
|
101
|
+
|
|
102
|
+
// Custom timeout and base URL
|
|
103
|
+
const client = new IPCClient({
|
|
104
|
+
apiKey: 'YOUR_API_KEY',
|
|
105
|
+
timeout: 15000, // 15 seconds in milliseconds
|
|
106
|
+
baseUrl: 'https://custom-domain.com'
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const data = await client.getIPDetails();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### CommonJS Usage
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
const { IPCClient } = require('@artsnoa/ipc-sdk');
|
|
116
|
+
|
|
117
|
+
const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
118
|
+
|
|
119
|
+
client.getIPDetails().then(data => {
|
|
120
|
+
console.log(`IP: ${data.ip}, Country: ${data.country}`);
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Error Handling
|
|
125
|
+
|
|
126
|
+
The SDK provides a custom error class for handling API errors:
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
import { IPCClient, IPCError } from '@artsnoa/ipc-sdk';
|
|
130
|
+
|
|
131
|
+
const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const data = await client.getIPDetails();
|
|
135
|
+
console.log(`Your IP: ${data.ip}`);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (error instanceof IPCError) {
|
|
138
|
+
console.error(`IPC Error: ${error.message}`);
|
|
139
|
+
if (error.statusCode) {
|
|
140
|
+
console.error(`Status code: ${error.statusCode}`);
|
|
141
|
+
}
|
|
142
|
+
if (error.code) {
|
|
143
|
+
console.error(`Error code: ${error.code}`);
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
console.error(`Unexpected error: ${error}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### TypeScript Error Handling
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { IPCClient, IPCError } from '@artsnoa/ipc-sdk';
|
|
155
|
+
|
|
156
|
+
const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
157
|
+
|
|
158
|
+
async function getIPSafely() {
|
|
159
|
+
try {
|
|
160
|
+
const data = await client.getIPDetails();
|
|
161
|
+
return data;
|
|
162
|
+
} catch (error) {
|
|
163
|
+
if (error instanceof IPCError) {
|
|
164
|
+
console.error(`API error: ${error.message}`);
|
|
165
|
+
console.error(`Status: ${error.statusCode ?? 'unknown'}`);
|
|
166
|
+
} else if (error instanceof Error) {
|
|
167
|
+
console.error(`Error: ${error.message}`);
|
|
168
|
+
}
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## API Reference
|
|
175
|
+
|
|
176
|
+
### IPCClient
|
|
177
|
+
|
|
178
|
+
#### Constructor
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
new IPCClient(options?: IPCClientOptions)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Parameters:**
|
|
185
|
+
- `options` (IPCClientOptions): Configuration options
|
|
186
|
+
- `apiKey` (string, optional): API key for authentication
|
|
187
|
+
- `baseUrl` (string, optional): Base URL for the API. Defaults to `https://ipc.artsnoa.com`
|
|
188
|
+
- `timeout` (number, optional): Request timeout in milliseconds. Defaults to 10000 (10 seconds)
|
|
189
|
+
|
|
190
|
+
**Example:**
|
|
191
|
+
```javascript
|
|
192
|
+
const client = new IPCClient({
|
|
193
|
+
apiKey: 'YOUR_API_KEY',
|
|
194
|
+
timeout: 15000,
|
|
195
|
+
baseUrl: 'https://ipc.artsnoa.com'
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Methods
|
|
200
|
+
|
|
201
|
+
##### `getIPDetails(): Promise<IPDetailsResponse>`
|
|
202
|
+
|
|
203
|
+
Get detailed IP address and location information.
|
|
204
|
+
|
|
205
|
+
**Returns:**
|
|
206
|
+
- Promise that resolves to an object containing:
|
|
207
|
+
- `ip` (string): Your IP address
|
|
208
|
+
- `userAgent` (string): Browser user agent string
|
|
209
|
+
- `asn` (string): Autonomous System Number
|
|
210
|
+
- `country` (string): Country code (ISO 3166-1 alpha-2)
|
|
211
|
+
- `currency` (string): Country currency code (ISO 4217)
|
|
212
|
+
- `languages` (string[]): Array of supported language codes
|
|
213
|
+
- `timestamp` (string): Request timestamp (ISO 8601 format)
|
|
214
|
+
- `version` (string): API version
|
|
215
|
+
|
|
216
|
+
**Throws:**
|
|
217
|
+
- `IPCError`: When the API request fails or returns an invalid response
|
|
218
|
+
|
|
219
|
+
**Example:**
|
|
220
|
+
```javascript
|
|
221
|
+
const details = await client.getIPDetails();
|
|
222
|
+
console.log(`IP: ${details.ip}, Country: ${details.country}`);
|
|
223
|
+
console.log(`ASN: ${details.asn}, Currency: ${details.currency}`);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
##### `getSDKVersions(): Promise<SDKVersionsResponse>`
|
|
227
|
+
|
|
228
|
+
Get available SDK versions for different platforms.
|
|
229
|
+
|
|
230
|
+
**Returns:**
|
|
231
|
+
- Promise that resolves to an object containing:
|
|
232
|
+
- `javascript` (string): JavaScript/TypeScript SDK version
|
|
233
|
+
- `python` (string): Python SDK version
|
|
234
|
+
|
|
235
|
+
**Throws:**
|
|
236
|
+
- `IPCError`: When the API request fails or returns an invalid response
|
|
237
|
+
|
|
238
|
+
**Example:**
|
|
239
|
+
```javascript
|
|
240
|
+
const versions = await client.getSDKVersions();
|
|
241
|
+
console.log(`JavaScript SDK: ${versions.javascript}`);
|
|
242
|
+
console.log(`Python SDK: ${versions.python}`);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Types
|
|
246
|
+
|
|
247
|
+
#### IPCClientOptions
|
|
248
|
+
|
|
249
|
+
Configuration options for the IPCClient constructor.
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
interface IPCClientOptions {
|
|
253
|
+
apiKey?: string;
|
|
254
|
+
baseUrl?: string;
|
|
255
|
+
timeout?: number;
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
#### IPDetailsResponse
|
|
260
|
+
|
|
261
|
+
Response structure from the `getIPDetails()` method.
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
interface IPDetailsResponse {
|
|
265
|
+
ip: string;
|
|
266
|
+
userAgent: string;
|
|
267
|
+
asn: string;
|
|
268
|
+
country: string;
|
|
269
|
+
currency: string;
|
|
270
|
+
languages: string[];
|
|
271
|
+
timestamp: string;
|
|
272
|
+
version: string;
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### SDKVersionsResponse
|
|
277
|
+
|
|
278
|
+
Response structure from the `getSDKVersions()` method.
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
interface SDKVersionsResponse {
|
|
282
|
+
javascript: string;
|
|
283
|
+
python: string;
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
#### IPCError
|
|
288
|
+
|
|
289
|
+
Custom error class for IPC SDK errors.
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
class IPCError extends Error {
|
|
293
|
+
statusCode?: number;
|
|
294
|
+
code?: string;
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Development
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
# Clone repository
|
|
302
|
+
git clone https://github.com/artsnoa/ipc-javascript-sdk.git
|
|
303
|
+
cd ipc-javascript-sdk
|
|
304
|
+
|
|
305
|
+
# Install dependencies
|
|
306
|
+
pnpm install
|
|
307
|
+
|
|
308
|
+
# Build package
|
|
309
|
+
pnpm run build
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Requirements
|
|
313
|
+
|
|
314
|
+
- Node.js 18.0.0 or higher
|
|
315
|
+
- No external runtime dependencies
|
|
316
|
+
|
|
317
|
+
## License
|
|
318
|
+
|
|
319
|
+
MIT License
|
|
320
|
+
|
|
321
|
+
## Support
|
|
322
|
+
|
|
323
|
+
- Documentation: [https://github.com/artsnoa/ipc-javascript-sdk](https://github.com/artsnoa/ipc-javascript-sdk)
|
|
324
|
+
- Issues: [https://github.com/artsnoa/ipc-javascript-sdk/issues](https://github.com/artsnoa/ipc-javascript-sdk/issues)
|
|
325
|
+
- Email: aurora@artsnoa.com
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for IPCClient
|
|
3
|
+
*/
|
|
4
|
+
interface IPCClientOptions {
|
|
5
|
+
/**
|
|
6
|
+
* API key for authentication (optional)
|
|
7
|
+
*/
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Base URL for the IPC API
|
|
11
|
+
* @default 'https://ipc.artsnoa.com'
|
|
12
|
+
*/
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Request timeout in milliseconds
|
|
16
|
+
* @default 10000
|
|
17
|
+
*/
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Response from the IP API
|
|
22
|
+
*/
|
|
23
|
+
interface IPResponse {
|
|
24
|
+
/**
|
|
25
|
+
* IP address
|
|
26
|
+
*/
|
|
27
|
+
ip: string;
|
|
28
|
+
/**
|
|
29
|
+
* Country code (ISO 3166-1 alpha-2)
|
|
30
|
+
*/
|
|
31
|
+
country: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Response from the IP details API
|
|
35
|
+
*/
|
|
36
|
+
interface IPDetailsResponse {
|
|
37
|
+
/**
|
|
38
|
+
* IP address
|
|
39
|
+
*/
|
|
40
|
+
ip: string;
|
|
41
|
+
/**
|
|
42
|
+
* User agent string
|
|
43
|
+
*/
|
|
44
|
+
userAgent: string;
|
|
45
|
+
/**
|
|
46
|
+
* Autonomous System Number
|
|
47
|
+
*/
|
|
48
|
+
asn: string;
|
|
49
|
+
/**
|
|
50
|
+
* Country code (ISO 3166-1 alpha-2)
|
|
51
|
+
*/
|
|
52
|
+
country: string;
|
|
53
|
+
/**
|
|
54
|
+
* Currency code (ISO 4217)
|
|
55
|
+
*/
|
|
56
|
+
currency: string;
|
|
57
|
+
/**
|
|
58
|
+
* Array of language codes
|
|
59
|
+
*/
|
|
60
|
+
languages: string[];
|
|
61
|
+
/**
|
|
62
|
+
* Timestamp of the request (ISO 8601 format)
|
|
63
|
+
*/
|
|
64
|
+
timestamp: string;
|
|
65
|
+
/**
|
|
66
|
+
* API version
|
|
67
|
+
*/
|
|
68
|
+
version: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Response from the SDK versions API
|
|
72
|
+
*/
|
|
73
|
+
interface SDKVersionsResponse {
|
|
74
|
+
/**
|
|
75
|
+
* JavaScript SDK version
|
|
76
|
+
*/
|
|
77
|
+
javascript: string;
|
|
78
|
+
/**
|
|
79
|
+
* Python SDK version
|
|
80
|
+
*/
|
|
81
|
+
python: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Custom error class for IPC SDK errors
|
|
85
|
+
*/
|
|
86
|
+
declare class IPCError extends Error {
|
|
87
|
+
readonly statusCode?: number;
|
|
88
|
+
readonly code?: string;
|
|
89
|
+
constructor(message: string, statusCode?: number, code?: string);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* IPCClient - Client for interacting with the IPC API
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
98
|
+
* const data = await client.getIPDetails();
|
|
99
|
+
* console.log(data);
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
declare class IPCClient {
|
|
103
|
+
private readonly baseUrls;
|
|
104
|
+
private readonly apiKey?;
|
|
105
|
+
private readonly timeout;
|
|
106
|
+
/**
|
|
107
|
+
* Creates a new IPCClient instance
|
|
108
|
+
*
|
|
109
|
+
* @param options - Configuration options
|
|
110
|
+
*/
|
|
111
|
+
constructor(options?: IPCClientOptions);
|
|
112
|
+
/**
|
|
113
|
+
* Retrieves basic IP information from the API
|
|
114
|
+
*
|
|
115
|
+
* @returns IP information with country code
|
|
116
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
121
|
+
* try {
|
|
122
|
+
* const data = await client.getIP();
|
|
123
|
+
* console.log(`Your IP: ${data.ip}, Country: ${data.country}`);
|
|
124
|
+
* } catch (error) {
|
|
125
|
+
* if (error instanceof IPCError) {
|
|
126
|
+
* console.error(`Error: ${error.message}`);
|
|
127
|
+
* }
|
|
128
|
+
* }
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
getIP(): Promise<IPResponse>;
|
|
132
|
+
/**
|
|
133
|
+
* Retrieves IP details from the API
|
|
134
|
+
*
|
|
135
|
+
* @returns IP details response
|
|
136
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* const client = new IPCClient();
|
|
141
|
+
* try {
|
|
142
|
+
* const details = await client.getIPDetails();
|
|
143
|
+
* console.log(`IP: ${details.ip}, Country: ${details.country}`);
|
|
144
|
+
* } catch (error) {
|
|
145
|
+
* if (error instanceof IPCError) {
|
|
146
|
+
* console.error(`Error: ${error.message}`);
|
|
147
|
+
* }
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
getIPDetails(): Promise<IPDetailsResponse>;
|
|
152
|
+
/**
|
|
153
|
+
* Retrieves SDK versions from the API
|
|
154
|
+
*
|
|
155
|
+
* @returns SDK versions response
|
|
156
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
161
|
+
* try {
|
|
162
|
+
* const versions = await client.getSDKVersions();
|
|
163
|
+
* console.log('SDK Versions:', versions);
|
|
164
|
+
* } catch (error) {
|
|
165
|
+
* if (error instanceof IPCError) {
|
|
166
|
+
* console.error(`Error: ${error.message}`);
|
|
167
|
+
* }
|
|
168
|
+
* }
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
getSDKVersions(): Promise<SDKVersionsResponse>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export { IPCClient, type IPCClientOptions, IPCError, type IPDetailsResponse, type IPResponse, type SDKVersionsResponse };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for IPCClient
|
|
3
|
+
*/
|
|
4
|
+
interface IPCClientOptions {
|
|
5
|
+
/**
|
|
6
|
+
* API key for authentication (optional)
|
|
7
|
+
*/
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Base URL for the IPC API
|
|
11
|
+
* @default 'https://ipc.artsnoa.com'
|
|
12
|
+
*/
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Request timeout in milliseconds
|
|
16
|
+
* @default 10000
|
|
17
|
+
*/
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Response from the IP API
|
|
22
|
+
*/
|
|
23
|
+
interface IPResponse {
|
|
24
|
+
/**
|
|
25
|
+
* IP address
|
|
26
|
+
*/
|
|
27
|
+
ip: string;
|
|
28
|
+
/**
|
|
29
|
+
* Country code (ISO 3166-1 alpha-2)
|
|
30
|
+
*/
|
|
31
|
+
country: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Response from the IP details API
|
|
35
|
+
*/
|
|
36
|
+
interface IPDetailsResponse {
|
|
37
|
+
/**
|
|
38
|
+
* IP address
|
|
39
|
+
*/
|
|
40
|
+
ip: string;
|
|
41
|
+
/**
|
|
42
|
+
* User agent string
|
|
43
|
+
*/
|
|
44
|
+
userAgent: string;
|
|
45
|
+
/**
|
|
46
|
+
* Autonomous System Number
|
|
47
|
+
*/
|
|
48
|
+
asn: string;
|
|
49
|
+
/**
|
|
50
|
+
* Country code (ISO 3166-1 alpha-2)
|
|
51
|
+
*/
|
|
52
|
+
country: string;
|
|
53
|
+
/**
|
|
54
|
+
* Currency code (ISO 4217)
|
|
55
|
+
*/
|
|
56
|
+
currency: string;
|
|
57
|
+
/**
|
|
58
|
+
* Array of language codes
|
|
59
|
+
*/
|
|
60
|
+
languages: string[];
|
|
61
|
+
/**
|
|
62
|
+
* Timestamp of the request (ISO 8601 format)
|
|
63
|
+
*/
|
|
64
|
+
timestamp: string;
|
|
65
|
+
/**
|
|
66
|
+
* API version
|
|
67
|
+
*/
|
|
68
|
+
version: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Response from the SDK versions API
|
|
72
|
+
*/
|
|
73
|
+
interface SDKVersionsResponse {
|
|
74
|
+
/**
|
|
75
|
+
* JavaScript SDK version
|
|
76
|
+
*/
|
|
77
|
+
javascript: string;
|
|
78
|
+
/**
|
|
79
|
+
* Python SDK version
|
|
80
|
+
*/
|
|
81
|
+
python: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Custom error class for IPC SDK errors
|
|
85
|
+
*/
|
|
86
|
+
declare class IPCError extends Error {
|
|
87
|
+
readonly statusCode?: number;
|
|
88
|
+
readonly code?: string;
|
|
89
|
+
constructor(message: string, statusCode?: number, code?: string);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* IPCClient - Client for interacting with the IPC API
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
98
|
+
* const data = await client.getIPDetails();
|
|
99
|
+
* console.log(data);
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
declare class IPCClient {
|
|
103
|
+
private readonly baseUrls;
|
|
104
|
+
private readonly apiKey?;
|
|
105
|
+
private readonly timeout;
|
|
106
|
+
/**
|
|
107
|
+
* Creates a new IPCClient instance
|
|
108
|
+
*
|
|
109
|
+
* @param options - Configuration options
|
|
110
|
+
*/
|
|
111
|
+
constructor(options?: IPCClientOptions);
|
|
112
|
+
/**
|
|
113
|
+
* Retrieves basic IP information from the API
|
|
114
|
+
*
|
|
115
|
+
* @returns IP information with country code
|
|
116
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
121
|
+
* try {
|
|
122
|
+
* const data = await client.getIP();
|
|
123
|
+
* console.log(`Your IP: ${data.ip}, Country: ${data.country}`);
|
|
124
|
+
* } catch (error) {
|
|
125
|
+
* if (error instanceof IPCError) {
|
|
126
|
+
* console.error(`Error: ${error.message}`);
|
|
127
|
+
* }
|
|
128
|
+
* }
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
getIP(): Promise<IPResponse>;
|
|
132
|
+
/**
|
|
133
|
+
* Retrieves IP details from the API
|
|
134
|
+
*
|
|
135
|
+
* @returns IP details response
|
|
136
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* const client = new IPCClient();
|
|
141
|
+
* try {
|
|
142
|
+
* const details = await client.getIPDetails();
|
|
143
|
+
* console.log(`IP: ${details.ip}, Country: ${details.country}`);
|
|
144
|
+
* } catch (error) {
|
|
145
|
+
* if (error instanceof IPCError) {
|
|
146
|
+
* console.error(`Error: ${error.message}`);
|
|
147
|
+
* }
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
getIPDetails(): Promise<IPDetailsResponse>;
|
|
152
|
+
/**
|
|
153
|
+
* Retrieves SDK versions from the API
|
|
154
|
+
*
|
|
155
|
+
* @returns SDK versions response
|
|
156
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
161
|
+
* try {
|
|
162
|
+
* const versions = await client.getSDKVersions();
|
|
163
|
+
* console.log('SDK Versions:', versions);
|
|
164
|
+
* } catch (error) {
|
|
165
|
+
* if (error instanceof IPCError) {
|
|
166
|
+
* console.error(`Error: ${error.message}`);
|
|
167
|
+
* }
|
|
168
|
+
* }
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
getSDKVersions(): Promise<SDKVersionsResponse>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export { IPCClient, type IPCClientOptions, IPCError, type IPDetailsResponse, type IPResponse, type SDKVersionsResponse };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
IPCClient: () => IPCClient,
|
|
24
|
+
IPCError: () => IPCError
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/types.ts
|
|
29
|
+
var IPCError = class _IPCError extends Error {
|
|
30
|
+
constructor(message, statusCode, code) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = "IPCError";
|
|
33
|
+
this.statusCode = statusCode;
|
|
34
|
+
this.code = code;
|
|
35
|
+
if (typeof Error.captureStackTrace === "function") {
|
|
36
|
+
Error.captureStackTrace(this, _IPCError);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// src/modules/constants.ts
|
|
42
|
+
var DEFAULT_BASE_URL = "https://ipc.artsnoa.com";
|
|
43
|
+
var FALLBACK_BASE_URL = "https://ipc.makedns.net";
|
|
44
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
45
|
+
var API_VERSION = "v1";
|
|
46
|
+
|
|
47
|
+
// src/modules/url-utils.ts
|
|
48
|
+
function sanitizeBaseUrl(url) {
|
|
49
|
+
try {
|
|
50
|
+
const parsedUrl = new URL(url);
|
|
51
|
+
if (parsedUrl.protocol !== "https:") {
|
|
52
|
+
throw new IPCError("Base URL must use https protocol. HTTP is not allowed for security reasons");
|
|
53
|
+
}
|
|
54
|
+
return parsedUrl.origin + parsedUrl.pathname.replace(/\/$/, "");
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (error instanceof IPCError) {
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
throw new IPCError(`Invalid base URL: ${url}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function buildUrl(baseUrl, path) {
|
|
63
|
+
const sanitizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
64
|
+
return `${baseUrl}${sanitizedPath}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/modules/validators.ts
|
|
68
|
+
function validateIPResponse(data) {
|
|
69
|
+
if (!data || typeof data !== "object") {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const response = data;
|
|
73
|
+
return typeof response.ip === "string" && typeof response.country === "string";
|
|
74
|
+
}
|
|
75
|
+
function validateIPDetailsResponse(data) {
|
|
76
|
+
if (!data || typeof data !== "object") {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
const response = data;
|
|
80
|
+
return typeof response.ip === "string" && typeof response.userAgent === "string" && typeof response.asn === "string" && typeof response.country === "string" && typeof response.currency === "string" && Array.isArray(response.languages) && response.languages.every((lang) => typeof lang === "string") && typeof response.timestamp === "string" && typeof response.version === "string";
|
|
81
|
+
}
|
|
82
|
+
function validateSDKVersionsResponse(data) {
|
|
83
|
+
if (!data || typeof data !== "object") {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const response = data;
|
|
87
|
+
return typeof response.javascript === "string" && typeof response.python === "string";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/modules/http-client.ts
|
|
91
|
+
async function makeRequestWithFallback(urls, apiKey, timeout) {
|
|
92
|
+
let lastError = null;
|
|
93
|
+
for (let i = 0; i < urls.length; i++) {
|
|
94
|
+
try {
|
|
95
|
+
return await makeRequest(urls[i], apiKey, timeout);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
lastError = error;
|
|
98
|
+
if (i < urls.length - 1) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
throw lastError || new IPCError("All requests failed");
|
|
104
|
+
}
|
|
105
|
+
async function makeRequest(url, apiKey, timeout) {
|
|
106
|
+
const controller = new AbortController();
|
|
107
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
108
|
+
try {
|
|
109
|
+
const headers = {
|
|
110
|
+
"Content-Type": "application/json",
|
|
111
|
+
"Accept": "application/json"
|
|
112
|
+
};
|
|
113
|
+
if (apiKey) {
|
|
114
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
115
|
+
}
|
|
116
|
+
const response = await fetch(url, {
|
|
117
|
+
method: "GET",
|
|
118
|
+
headers,
|
|
119
|
+
signal: controller.signal
|
|
120
|
+
});
|
|
121
|
+
clearTimeout(timeoutId);
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
124
|
+
let errorCode;
|
|
125
|
+
try {
|
|
126
|
+
const errorData = await response.json();
|
|
127
|
+
if (errorData.message) {
|
|
128
|
+
errorMessage = errorData.message;
|
|
129
|
+
}
|
|
130
|
+
if (errorData.code) {
|
|
131
|
+
errorCode = errorData.code;
|
|
132
|
+
}
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
throw new IPCError(errorMessage, response.status, errorCode);
|
|
136
|
+
}
|
|
137
|
+
const contentType = response.headers.get("Content-Type");
|
|
138
|
+
if (!contentType || !contentType.includes("application/json")) {
|
|
139
|
+
throw new IPCError("Invalid response content type. Expected application/json");
|
|
140
|
+
}
|
|
141
|
+
const data = await response.json();
|
|
142
|
+
return data;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
clearTimeout(timeoutId);
|
|
145
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
146
|
+
throw new IPCError(`Request timeout after ${timeout}ms`);
|
|
147
|
+
}
|
|
148
|
+
if (error instanceof IPCError) {
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
if (error instanceof TypeError) {
|
|
152
|
+
throw new IPCError(`Network error: ${error.message}`);
|
|
153
|
+
}
|
|
154
|
+
throw new IPCError(
|
|
155
|
+
error instanceof Error ? error.message : "An unknown error occurred"
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/functions/getIP.ts
|
|
161
|
+
async function getIP(baseUrls, apiKey, timeout) {
|
|
162
|
+
const urls = baseUrls.map((baseUrl) => buildUrl(baseUrl, `/api/${API_VERSION}/ip`));
|
|
163
|
+
const data = await makeRequestWithFallback(urls, apiKey, timeout);
|
|
164
|
+
if (!validateIPResponse(data)) {
|
|
165
|
+
throw new IPCError("Invalid response structure from API");
|
|
166
|
+
}
|
|
167
|
+
return data;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/functions/getIPDetails.ts
|
|
171
|
+
async function getIPDetails(baseUrls, apiKey, timeout) {
|
|
172
|
+
const urls = baseUrls.map((baseUrl) => buildUrl(baseUrl, `/api/${API_VERSION}/ip/details`));
|
|
173
|
+
const data = await makeRequestWithFallback(urls, apiKey, timeout);
|
|
174
|
+
if (!validateIPDetailsResponse(data)) {
|
|
175
|
+
throw new IPCError("Invalid response structure from API");
|
|
176
|
+
}
|
|
177
|
+
return data;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/functions/getSDKVersions.ts
|
|
181
|
+
async function getSDKVersions(baseUrls, apiKey, timeout) {
|
|
182
|
+
const urls = baseUrls.map((baseUrl) => buildUrl(baseUrl, `/api/${API_VERSION}/sdk/version`));
|
|
183
|
+
const data = await makeRequestWithFallback(urls, apiKey, timeout);
|
|
184
|
+
if (!validateSDKVersionsResponse(data)) {
|
|
185
|
+
throw new IPCError("Invalid response structure from API");
|
|
186
|
+
}
|
|
187
|
+
return data;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// src/client.ts
|
|
191
|
+
var IPCClient = class {
|
|
192
|
+
/**
|
|
193
|
+
* Creates a new IPCClient instance
|
|
194
|
+
*
|
|
195
|
+
* @param options - Configuration options
|
|
196
|
+
*/
|
|
197
|
+
constructor(options = {}) {
|
|
198
|
+
if (options.baseUrl) {
|
|
199
|
+
this.baseUrls = [sanitizeBaseUrl(options.baseUrl)];
|
|
200
|
+
} else {
|
|
201
|
+
this.baseUrls = [
|
|
202
|
+
sanitizeBaseUrl(DEFAULT_BASE_URL),
|
|
203
|
+
sanitizeBaseUrl(FALLBACK_BASE_URL)
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
this.apiKey = options.apiKey;
|
|
207
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
208
|
+
if (this.timeout <= 0 || this.timeout > 6e4) {
|
|
209
|
+
throw new IPCError("Timeout must be between 1 and 60000 milliseconds");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Retrieves basic IP information from the API
|
|
214
|
+
*
|
|
215
|
+
* @returns IP information with country code
|
|
216
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
221
|
+
* try {
|
|
222
|
+
* const data = await client.getIP();
|
|
223
|
+
* console.log(`Your IP: ${data.ip}, Country: ${data.country}`);
|
|
224
|
+
* } catch (error) {
|
|
225
|
+
* if (error instanceof IPCError) {
|
|
226
|
+
* console.error(`Error: ${error.message}`);
|
|
227
|
+
* }
|
|
228
|
+
* }
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
async getIP() {
|
|
232
|
+
return getIP(this.baseUrls, this.apiKey, this.timeout);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Retrieves IP details from the API
|
|
236
|
+
*
|
|
237
|
+
* @returns IP details response
|
|
238
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript
|
|
242
|
+
* const client = new IPCClient();
|
|
243
|
+
* try {
|
|
244
|
+
* const details = await client.getIPDetails();
|
|
245
|
+
* console.log(`IP: ${details.ip}, Country: ${details.country}`);
|
|
246
|
+
* } catch (error) {
|
|
247
|
+
* if (error instanceof IPCError) {
|
|
248
|
+
* console.error(`Error: ${error.message}`);
|
|
249
|
+
* }
|
|
250
|
+
* }
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
async getIPDetails() {
|
|
254
|
+
return getIPDetails(this.baseUrls, this.apiKey, this.timeout);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Retrieves SDK versions from the API
|
|
258
|
+
*
|
|
259
|
+
* @returns SDK versions response
|
|
260
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```typescript
|
|
264
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
265
|
+
* try {
|
|
266
|
+
* const versions = await client.getSDKVersions();
|
|
267
|
+
* console.log('SDK Versions:', versions);
|
|
268
|
+
* } catch (error) {
|
|
269
|
+
* if (error instanceof IPCError) {
|
|
270
|
+
* console.error(`Error: ${error.message}`);
|
|
271
|
+
* }
|
|
272
|
+
* }
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
async getSDKVersions() {
|
|
276
|
+
return getSDKVersions(this.baseUrls, this.apiKey, this.timeout);
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
280
|
+
0 && (module.exports = {
|
|
281
|
+
IPCClient,
|
|
282
|
+
IPCError
|
|
283
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var IPCError = class _IPCError extends Error {
|
|
3
|
+
constructor(message, statusCode, code) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "IPCError";
|
|
6
|
+
this.statusCode = statusCode;
|
|
7
|
+
this.code = code;
|
|
8
|
+
if (typeof Error.captureStackTrace === "function") {
|
|
9
|
+
Error.captureStackTrace(this, _IPCError);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// src/modules/constants.ts
|
|
15
|
+
var DEFAULT_BASE_URL = "https://ipc.artsnoa.com";
|
|
16
|
+
var FALLBACK_BASE_URL = "https://ipc.makedns.net";
|
|
17
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
18
|
+
var API_VERSION = "v1";
|
|
19
|
+
|
|
20
|
+
// src/modules/url-utils.ts
|
|
21
|
+
function sanitizeBaseUrl(url) {
|
|
22
|
+
try {
|
|
23
|
+
const parsedUrl = new URL(url);
|
|
24
|
+
if (parsedUrl.protocol !== "https:") {
|
|
25
|
+
throw new IPCError("Base URL must use https protocol. HTTP is not allowed for security reasons");
|
|
26
|
+
}
|
|
27
|
+
return parsedUrl.origin + parsedUrl.pathname.replace(/\/$/, "");
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error instanceof IPCError) {
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
throw new IPCError(`Invalid base URL: ${url}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function buildUrl(baseUrl, path) {
|
|
36
|
+
const sanitizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
37
|
+
return `${baseUrl}${sanitizedPath}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/modules/validators.ts
|
|
41
|
+
function validateIPResponse(data) {
|
|
42
|
+
if (!data || typeof data !== "object") {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const response = data;
|
|
46
|
+
return typeof response.ip === "string" && typeof response.country === "string";
|
|
47
|
+
}
|
|
48
|
+
function validateIPDetailsResponse(data) {
|
|
49
|
+
if (!data || typeof data !== "object") {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const response = data;
|
|
53
|
+
return typeof response.ip === "string" && typeof response.userAgent === "string" && typeof response.asn === "string" && typeof response.country === "string" && typeof response.currency === "string" && Array.isArray(response.languages) && response.languages.every((lang) => typeof lang === "string") && typeof response.timestamp === "string" && typeof response.version === "string";
|
|
54
|
+
}
|
|
55
|
+
function validateSDKVersionsResponse(data) {
|
|
56
|
+
if (!data || typeof data !== "object") {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const response = data;
|
|
60
|
+
return typeof response.javascript === "string" && typeof response.python === "string";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/modules/http-client.ts
|
|
64
|
+
async function makeRequestWithFallback(urls, apiKey, timeout) {
|
|
65
|
+
let lastError = null;
|
|
66
|
+
for (let i = 0; i < urls.length; i++) {
|
|
67
|
+
try {
|
|
68
|
+
return await makeRequest(urls[i], apiKey, timeout);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
lastError = error;
|
|
71
|
+
if (i < urls.length - 1) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
throw lastError || new IPCError("All requests failed");
|
|
77
|
+
}
|
|
78
|
+
async function makeRequest(url, apiKey, timeout) {
|
|
79
|
+
const controller = new AbortController();
|
|
80
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
81
|
+
try {
|
|
82
|
+
const headers = {
|
|
83
|
+
"Content-Type": "application/json",
|
|
84
|
+
"Accept": "application/json"
|
|
85
|
+
};
|
|
86
|
+
if (apiKey) {
|
|
87
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
88
|
+
}
|
|
89
|
+
const response = await fetch(url, {
|
|
90
|
+
method: "GET",
|
|
91
|
+
headers,
|
|
92
|
+
signal: controller.signal
|
|
93
|
+
});
|
|
94
|
+
clearTimeout(timeoutId);
|
|
95
|
+
if (!response.ok) {
|
|
96
|
+
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
97
|
+
let errorCode;
|
|
98
|
+
try {
|
|
99
|
+
const errorData = await response.json();
|
|
100
|
+
if (errorData.message) {
|
|
101
|
+
errorMessage = errorData.message;
|
|
102
|
+
}
|
|
103
|
+
if (errorData.code) {
|
|
104
|
+
errorCode = errorData.code;
|
|
105
|
+
}
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
108
|
+
throw new IPCError(errorMessage, response.status, errorCode);
|
|
109
|
+
}
|
|
110
|
+
const contentType = response.headers.get("Content-Type");
|
|
111
|
+
if (!contentType || !contentType.includes("application/json")) {
|
|
112
|
+
throw new IPCError("Invalid response content type. Expected application/json");
|
|
113
|
+
}
|
|
114
|
+
const data = await response.json();
|
|
115
|
+
return data;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
clearTimeout(timeoutId);
|
|
118
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
119
|
+
throw new IPCError(`Request timeout after ${timeout}ms`);
|
|
120
|
+
}
|
|
121
|
+
if (error instanceof IPCError) {
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
if (error instanceof TypeError) {
|
|
125
|
+
throw new IPCError(`Network error: ${error.message}`);
|
|
126
|
+
}
|
|
127
|
+
throw new IPCError(
|
|
128
|
+
error instanceof Error ? error.message : "An unknown error occurred"
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/functions/getIP.ts
|
|
134
|
+
async function getIP(baseUrls, apiKey, timeout) {
|
|
135
|
+
const urls = baseUrls.map((baseUrl) => buildUrl(baseUrl, `/api/${API_VERSION}/ip`));
|
|
136
|
+
const data = await makeRequestWithFallback(urls, apiKey, timeout);
|
|
137
|
+
if (!validateIPResponse(data)) {
|
|
138
|
+
throw new IPCError("Invalid response structure from API");
|
|
139
|
+
}
|
|
140
|
+
return data;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/functions/getIPDetails.ts
|
|
144
|
+
async function getIPDetails(baseUrls, apiKey, timeout) {
|
|
145
|
+
const urls = baseUrls.map((baseUrl) => buildUrl(baseUrl, `/api/${API_VERSION}/ip/details`));
|
|
146
|
+
const data = await makeRequestWithFallback(urls, apiKey, timeout);
|
|
147
|
+
if (!validateIPDetailsResponse(data)) {
|
|
148
|
+
throw new IPCError("Invalid response structure from API");
|
|
149
|
+
}
|
|
150
|
+
return data;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/functions/getSDKVersions.ts
|
|
154
|
+
async function getSDKVersions(baseUrls, apiKey, timeout) {
|
|
155
|
+
const urls = baseUrls.map((baseUrl) => buildUrl(baseUrl, `/api/${API_VERSION}/sdk/version`));
|
|
156
|
+
const data = await makeRequestWithFallback(urls, apiKey, timeout);
|
|
157
|
+
if (!validateSDKVersionsResponse(data)) {
|
|
158
|
+
throw new IPCError("Invalid response structure from API");
|
|
159
|
+
}
|
|
160
|
+
return data;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/client.ts
|
|
164
|
+
var IPCClient = class {
|
|
165
|
+
/**
|
|
166
|
+
* Creates a new IPCClient instance
|
|
167
|
+
*
|
|
168
|
+
* @param options - Configuration options
|
|
169
|
+
*/
|
|
170
|
+
constructor(options = {}) {
|
|
171
|
+
if (options.baseUrl) {
|
|
172
|
+
this.baseUrls = [sanitizeBaseUrl(options.baseUrl)];
|
|
173
|
+
} else {
|
|
174
|
+
this.baseUrls = [
|
|
175
|
+
sanitizeBaseUrl(DEFAULT_BASE_URL),
|
|
176
|
+
sanitizeBaseUrl(FALLBACK_BASE_URL)
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
this.apiKey = options.apiKey;
|
|
180
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
181
|
+
if (this.timeout <= 0 || this.timeout > 6e4) {
|
|
182
|
+
throw new IPCError("Timeout must be between 1 and 60000 milliseconds");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Retrieves basic IP information from the API
|
|
187
|
+
*
|
|
188
|
+
* @returns IP information with country code
|
|
189
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```typescript
|
|
193
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
194
|
+
* try {
|
|
195
|
+
* const data = await client.getIP();
|
|
196
|
+
* console.log(`Your IP: ${data.ip}, Country: ${data.country}`);
|
|
197
|
+
* } catch (error) {
|
|
198
|
+
* if (error instanceof IPCError) {
|
|
199
|
+
* console.error(`Error: ${error.message}`);
|
|
200
|
+
* }
|
|
201
|
+
* }
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
async getIP() {
|
|
205
|
+
return getIP(this.baseUrls, this.apiKey, this.timeout);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Retrieves IP details from the API
|
|
209
|
+
*
|
|
210
|
+
* @returns IP details response
|
|
211
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* const client = new IPCClient();
|
|
216
|
+
* try {
|
|
217
|
+
* const details = await client.getIPDetails();
|
|
218
|
+
* console.log(`IP: ${details.ip}, Country: ${details.country}`);
|
|
219
|
+
* } catch (error) {
|
|
220
|
+
* if (error instanceof IPCError) {
|
|
221
|
+
* console.error(`Error: ${error.message}`);
|
|
222
|
+
* }
|
|
223
|
+
* }
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
async getIPDetails() {
|
|
227
|
+
return getIPDetails(this.baseUrls, this.apiKey, this.timeout);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Retrieves SDK versions from the API
|
|
231
|
+
*
|
|
232
|
+
* @returns SDK versions response
|
|
233
|
+
* @throws {IPCError} If the request fails or response is invalid
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```typescript
|
|
237
|
+
* const client = new IPCClient({ apiKey: 'YOUR_API_KEY' });
|
|
238
|
+
* try {
|
|
239
|
+
* const versions = await client.getSDKVersions();
|
|
240
|
+
* console.log('SDK Versions:', versions);
|
|
241
|
+
* } catch (error) {
|
|
242
|
+
* if (error instanceof IPCError) {
|
|
243
|
+
* console.error(`Error: ${error.message}`);
|
|
244
|
+
* }
|
|
245
|
+
* }
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
async getSDKVersions() {
|
|
249
|
+
return getSDKVersions(this.baseUrls, this.apiKey, this.timeout);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
export {
|
|
253
|
+
IPCClient,
|
|
254
|
+
IPCError
|
|
255
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@artsnoa/ipc-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript SDK for IPC API - IP address and country lookup",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
20
|
+
"prepublishOnly": "pnpm run build",
|
|
21
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"ipc",
|
|
25
|
+
"ip",
|
|
26
|
+
"geolocation",
|
|
27
|
+
"country",
|
|
28
|
+
"sdk",
|
|
29
|
+
"api"
|
|
30
|
+
],
|
|
31
|
+
"author": "Artsnoa.com(mirseo) <aurora@artsnoa.com>",
|
|
32
|
+
"license": "UNLICENSED",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/Artsnoa/IPC-Javascript-SDK.git"
|
|
36
|
+
},
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/Artsnoa/IPC-Javascript-SDK/issues"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://ipc.artsnoa.com",
|
|
41
|
+
"packageManager": "pnpm@10.28.2",
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^22.0.0",
|
|
44
|
+
"tsup": "^8.0.0",
|
|
45
|
+
"typescript": "^5.6.0"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|