Skip to content

Commit 543fec2

Browse files
committed
fix: Make cache configurable and cache biulk lookup responses
1 parent f0c6610 commit 543fec2

3 files changed

Lines changed: 36 additions & 26 deletions

File tree

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "ipdata",
33
"version": "2.0.0",
44
"description": "JavaScript library to gather information for an ip using https://ipdata.co.",
5-
"main": "./lib/index.js",
5+
"main": "./lib/ipdata.js",
66
"scripts": {
77
"prebuild": "del lib",
88
"build": "tsc",
@@ -24,7 +24,7 @@
2424
"is-ip": "^3.1.0",
2525
"lodash": "4.17.15",
2626
"lru-cache": "5.1.1",
27-
"tslib": "1.9.3",
27+
"tslib": "1.10.0",
2828
"url-join": "4.0.0"
2929
},
3030
"devDependencies": {

src/ipdata.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import LRU from 'lru-cache';
77

88
const CACHE_MAX = 4096; // max number of items
99
const CACHE_MAX_AGE = 1000 * 60 * 60 * 24; // 24 hours
10-
const cache = new LRU<string, LookupResponse>({ max: CACHE_MAX, maxAge: CACHE_MAX_AGE });
1110
const DEFAULT_IP = 'DEFAULT_IP';
1211
const VALID_FIELDS = [
1312
'ip',
@@ -67,12 +66,10 @@ function isValidFields(fields: string[]): boolean {
6766
return true;
6867
}
6968

70-
// export function clearCache(ip?: string): void {
71-
// if (isValidIP(ip)) {
72-
// return cache.del(ip);
73-
// }
74-
// return cache.reset();
75-
// }
69+
export interface CacheConfig {
70+
max?: number;
71+
maxAge?: number;
72+
}
7673

7774
export interface LookupResponse {
7875
ip: string;
@@ -139,15 +136,15 @@ interface IPDataParams {
139136

140137
export default class IPData {
141138
apiKey?: string;
142-
useCache?: boolean;
139+
cache?: LRU<string, LookupResponse>;
143140

144-
constructor(apiKey: string, useCache = true) {
141+
constructor(apiKey: string, cacheConfig?: CacheConfig) {
145142
if (!isString(apiKey)) {
146143
throw new Error('An API key is required.');
147144
}
148145

149146
this.apiKey = apiKey;
150-
this.useCache = useCache === true;
147+
this.cache = new LRU<string, LookupResponse>({ max: CACHE_MAX, maxAge: CACHE_MAX_AGE, ...cacheConfig });
151148
}
152149

153150
async lookup(ip?: string, selectField?: string, fields?: string[]): Promise<LookupResponse> {
@@ -158,8 +155,8 @@ export default class IPData {
158155
throw new Error(`${ip} is an invalid IP address.`);
159156
}
160157

161-
if (this.useCache && cache.has(ip || DEFAULT_IP)) {
162-
return cache.get(ip || DEFAULT_IP);
158+
if (this.cache.has(ip || DEFAULT_IP)) {
159+
return this.cache.get(ip || DEFAULT_IP);
163160
}
164161

165162
if (selectField && fields) {
@@ -182,11 +179,7 @@ export default class IPData {
182179
data = { [selectField]: response.data, status: response.status };
183180
}
184181

185-
if ((!selectField || !fields) && this.useCache) {
186-
cache.set(ip || DEFAULT_IP, data);
187-
} else {
188-
return data;
189-
}
182+
this.cache.set(ip || DEFAULT_IP, data);
190183
} catch (e) {
191184
const { response } = e as AxiosError;
192185
if (response) {
@@ -195,11 +188,13 @@ export default class IPData {
195188
throw e;
196189
}
197190

198-
return cache.get(ip || DEFAULT_IP);
191+
return this.cache.get(ip || DEFAULT_IP);
199192
}
200193

201194
async bulkLookup(ips: string[], fields?: string[]): Promise<BulkLookupResponse> {
202195
const params: IPDataParams = { 'api-key': this.apiKey };
196+
const responses: LookupResponse[] = [];
197+
const bulk = [];
203198

204199
if (ips.length < 2) {
205200
throw new Error('Bulk Lookup requires more than 1 IP Address in the payload.');
@@ -209,15 +204,30 @@ export default class IPData {
209204
if (!isValidIP(ip)) {
210205
throw new Error(`${ip} is an invalid IP address.`);
211206
}
207+
208+
if (this.cache.has(ip)) {
209+
responses.push(this.cache.get(ip));
210+
} else {
211+
bulk.push(ip);
212+
}
212213
});
213214

214215
if (fields && isValidFields(fields)) {
215216
params.fields = fields.join(',');
216217
}
217218

218219
try {
219-
const response = await axios.post(urljoin(BASE_URL, 'bulk'), ips, { params });
220-
return { responses: response.data, status: response.status };
220+
let result: BulkLookupResponse = { responses, status: 200 };
221+
222+
if (bulk.length > 0) {
223+
const response = await axios.post(urljoin(BASE_URL, 'bulk'), bulk, { params });
224+
response.data.forEach(info => {
225+
this.cache.set(info.ip, info);
226+
});
227+
result = { responses: [...responses, ...response.data], status: response.status };
228+
}
229+
230+
return result;
221231
} catch (e) {
222232
const { response } = e as AxiosError;
223233
if (response) {

0 commit comments

Comments
 (0)