Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 36 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,16 @@ Import the library.
import IPData from 'ipdata';
```

**Note:** If you are using `require()` then you will need to use the default value exported from the library.
A named export is also available:

```js
const IPData = require('ipdata').default;
import { IPData } from 'ipdata';
```

If you are using `require()`:

```js
const { IPData } = require('ipdata');
```

### Create an Instance
Expand Down Expand Up @@ -82,6 +88,8 @@ const ipdata = new IPData('<apiKey>', undefined, 'https://eu-api.ipdata.co/');

### Lookup

The `lookup()` method accepts either positional arguments or a single named-params object.

The library will lookup the ip address of the host computer if no ip address is provided.

```js
Expand All @@ -92,35 +100,48 @@ ipdata.lookup()
});
```

You can pass an ip address as the first parameter to the `lookup()` method to lookup information about the ip address using IPData.
You can pass an ip address to lookup information about it.

```js
const ip = '1.1.1.1';
ipdata.lookup(ip)
ipdata.lookup('1.1.1.1')
.then(function(info) {
// info.ip === 1.1.1.1
// info.ip === '1.1.1.1'
// ...
});
```

You can specify only a select field to be returned when looking up an ip address by passing a field as the second parameter to the `lookup()` method.
You can specify a single field to be returned.

```js
const ip = '1.1.1.1';
const selectField = 'ip';
ipdata.lookup(ip, selectField)
ipdata.lookup('1.1.1.1', 'ip')
.then(function(info) {
// info.select_field === 1.1.1.1
// info.ip === '1.1.1.1'
// ...
});
```

You can specify only certain fields to be returned when looking up an ip address by passing an array of fields as the third parameter to the `lookup()` method.
You can specify multiple fields to be returned.

```js
const ip = '1.1.1.1';
const fields = ['ip', 'city'];
ipdata.lookup(ip, null, fields)
ipdata.lookup('1.1.1.1', undefined, ['ip', 'city'])
.then(function(info) {
// ...
});
```

#### Named Parameters

You can also pass a single object, which is especially convenient when you only need `fields` or `selectField` without specifying an IP.

```js
// Lookup your own IP with specific fields
ipdata.lookup({ fields: ['ip', 'city'] })
.then(function(info) {
// ...
});

// Lookup a specific IP with a select field
ipdata.lookup({ ip: '1.1.1.1', selectField: 'city' })
.then(function(info) {
// ...
});
Expand Down
37 changes: 37 additions & 0 deletions src/ipdata.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import IPData, { EU_BASE_URL, LookupResponse } from './ipdata';

Check warning on line 1 in src/ipdata.test.ts

View workflow job for this annotation

GitHub Actions / lint

Using exported name 'IPData' as identifier for default import

const TEST_API_KEY = 'test-api-key';
const TEST_IP = '1.1.1.1';
Expand Down Expand Up @@ -261,6 +261,43 @@
});
});

describe('named params', () => {
it('should return information with no params', async () => {
mockFetch.mockReturnValueOnce(mockFetchResponse(MOCK_DEFAULT_IP_DATA));
const info = await ipdata.lookup({});
expect(info).toHaveProperty('ip');
expect(info).toHaveProperty('status');
});

it('should return information with ip param', async () => {
mockFetch.mockReturnValueOnce(mockFetchResponse(MOCK_IP1_DATA));
const info = await ipdata.lookup({ ip: TEST_IP });
expect(info).toHaveProperty('ip', TEST_IP);
expect(info).toHaveProperty('status');
});

it('should return a selectField response', async () => {
mockFetch.mockReturnValueOnce(mockFetchResponse(false));
const info = await ipdata.lookup({ selectField: 'is_eu' });
expect(info).toHaveProperty('is_eu', false);
expect(info).toHaveProperty('status');
});

it('should return a fields response', async () => {
mockFetch.mockReturnValueOnce(mockFetchResponse({ ip: TEST_IP, is_eu: false }));
const info = await ipdata.lookup({ ip: TEST_IP, fields: ['ip', 'is_eu'] });
expect(info).toHaveProperty('ip', TEST_IP);
expect(info).toHaveProperty('is_eu', false);
expect(info).toHaveProperty('status');
});

it('should throw if selectField and fields are both provided', async () => {
await expect(ipdata.lookup({ selectField: 'ip', fields: ['ip'] })).rejects.toThrow(
'The selectField and fields parameters cannot be used at the same time.',
);
});
});

describe('new API fields', () => {
it('should return threat object with new fields', async () => {
mockFetch.mockReturnValueOnce(mockFetchResponse(MOCK_IP1_DATA));
Expand Down
29 changes: 28 additions & 1 deletion src/ipdata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ export interface CacheConfig {
ttl?: number;
}

export interface LookupParams {
ip?: string;
selectField?: string;
fields?: string[];
}

export interface LookupResponse {
ip: string;
is_eu: boolean;
Expand Down Expand Up @@ -158,7 +164,28 @@ export class IPData {
return url;
}

async lookup(ip?: string, selectField?: string, fields?: string[]): Promise<LookupResponse> {
async lookup(params: LookupParams): Promise<LookupResponse>;
async lookup(ip?: string, selectField?: string, fields?: string[]): Promise<LookupResponse>;
async lookup(
ipOrParams?: string | LookupParams,
positionalSelectField?: string,
positionalFields?: string[],
): Promise<LookupResponse> {
let ip: string | undefined;
let selectField: string | undefined;
let fields: string[] | undefined;

if (typeof ipOrParams === 'object' && ipOrParams !== null) {
({ ip, selectField, fields } = ipOrParams);
} else if (typeof ipOrParams === 'string') {
ip = ipOrParams;
selectField = positionalSelectField;
fields = positionalFields;
} else {
selectField = positionalSelectField;
fields = positionalFields;
}

if (ip && !isValidIP(ip)) {
throw new Error(`${ip} is an invalid IP address.`);
}
Expand Down