builtwith-api 1.0.6 → 1.0.8

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/README.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  `builtwith-api` is a utility wrapper for the BuiltWith API suite.
4
4
 
5
+ Install using
6
+ ```
7
+ yarn install builtwith-api
8
+
9
+ or
10
+
11
+ npm install builtwith-api
12
+ ```
13
+
5
14
  ## Features
6
15
 
7
16
  Response Formats
@@ -25,7 +34,7 @@ ________________
25
34
  ## How To Use
26
35
 
27
36
  ```js
28
- const builtwith = require('builtwith')
37
+ const BuiltWith = require('builtwith-api')
29
38
 
30
39
  const builtwith = BuiltWith(process.env.YOUR_BUILTWITH_API_KEY, {
31
40
  responseFormat: 'json' // 'json' 'xml' 'txt' (only for lists API)
@@ -61,7 +70,9 @@ await builtwith.lists(technology, {
61
70
 
62
71
  await builtwith.relationships(url)
63
72
 
64
- await builtwith.keywords(url)
73
+ const urls = ['hotelscombined.com', 'builtwith.com']
74
+ // Multi-domain lookup. Will automatically be converted into URI encoded array (hotelscombined.com,builtwith.com).
75
+ await builtwith.keywords(urls)
65
76
 
66
77
  await builtwith.trends(technology, {
67
78
  // Totals will be the closest to this date - providing the ability to get historical totals
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "builtwith-api",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Wrapper for the BuiltWith API",
5
5
  "main": "src/index.js",
6
6
  "scripts": {},
@@ -14,11 +14,14 @@
14
14
  "BuiltWith",
15
15
  "apis"
16
16
  ],
17
+ "files": [
18
+ "src",
19
+ "src/utils"
20
+ ],
17
21
  "author": "Zach Caceres (@zachcaceres)",
18
22
  "license": "MIT",
19
23
  "dependencies": {
20
- "lodash": "^4.17.15",
21
- "node-fetch": "^2.6.0"
24
+ "lodash": "^4.17.15"
22
25
  },
23
26
  "devDependencies": {
24
27
  "dotenv": "^8.2.0"
package/src/index.js CHANGED
@@ -1,34 +1,44 @@
1
- const _ = require('lodash')
2
-
3
- const utils = require("./utils")
4
- const { VALID_RESPONSE_TYPES } = require("./config")
1
+ const _ = require("lodash");
5
2
 
3
+ const utils = require("./utils");
4
+ const { VALID_RESPONSE_TYPES } = require("./config");
6
5
 
7
6
  function BuiltWith(apiKey, moduleParams = {}) {
8
- const responseFormat = _.get(moduleParams, 'responseFormat', 'json')
7
+ const responseFormat = _.get(moduleParams, "responseFormat", "json");
9
8
 
10
9
  if (!Object.values(VALID_RESPONSE_TYPES).includes(responseFormat)) {
11
- throw new Error(`Invalid 'responseFormat'. Valid format are 'xml', 'txt', and 'json'. You input ${responseFormat}`)
10
+ throw new Error(
11
+ `Invalid 'responseFormat'. Valid format are 'xml', 'txt', and 'json'. You input ${responseFormat}`,
12
+ );
12
13
  }
13
14
 
14
15
  if (responseFormat === VALID_RESPONSE_TYPES.TXT) {
15
- console.warn("TXT response format is only supported for the BuiltWith Lists API. See: https://api.builtwith.com/lists-api");
16
+ console.warn(
17
+ "TXT response format is only supported for the BuiltWith Lists API. See: https://api.builtwith.com/lists-api",
18
+ );
16
19
  }
17
20
 
18
21
  function constructBuiltWithURL(
19
22
  apiName,
20
23
  requestParams = {},
21
- subdomain = 'api'
24
+ subdomain = "api",
22
25
  ) {
23
- let bwURL = `https://${subdomain}.builtwith.com/${apiName}/api.${responseFormat}?KEY=${apiKey}`
26
+ let bwURL = `https://${subdomain}.builtwith.com/${apiName}/api.${responseFormat}?KEY=${apiKey}`;
24
27
 
25
28
  if (!_.isEmpty(requestParams)) {
26
- bwURL += `&${utils.paramsObjToQueryString(requestParams)}`
29
+ bwURL += `&${utils.paramsObjToQueryString(requestParams)}`;
27
30
  }
28
31
 
29
- return bwURL
32
+ return bwURL;
30
33
  }
31
34
 
35
+ function checkUrlData(url, isMultiDomain = true) {
36
+ let isArray = Array.isArray(url);
37
+ if (isArray) {
38
+ if (!isMultiDomain) throw "API does not allow for multi-domain LOOKUP";
39
+ if (url.length > 16) throw "Domain LOOKUP size to big (16 max)";
40
+ }
41
+ }
32
42
 
33
43
  return {
34
44
  /**
@@ -37,12 +47,14 @@ function BuiltWith(apiKey, moduleParams = {}) {
37
47
  * @see https://api.builtwith.com/free-api
38
48
  * @param {String} url
39
49
  */
40
- free: async function(url) {
50
+ free: async function (url) {
51
+ checkUrlData(url, false);
52
+
41
53
  const bwURL = constructBuiltWithURL("free1", {
42
- LOOKUP: url
54
+ LOOKUP: url,
43
55
  });
44
56
 
45
- const res = await utils.makeStandardRequest(bwURL, responseFormat)
57
+ const res = await utils.makeStandardRequest(bwURL, responseFormat);
46
58
  return res;
47
59
  },
48
60
 
@@ -50,27 +62,28 @@ function BuiltWith(apiKey, moduleParams = {}) {
50
62
  * Make a request to the BuiltWith Domain API
51
63
  *
52
64
  * @see https://api.builtwith.com/domain-api
53
- * @param {String} url
65
+ * @param {(string|string[])} url
54
66
  * @param {Object} params
55
67
  */
56
- domain: async function(url, params) {
68
+ domain: async function (url, params) {
69
+ checkUrlData(url);
57
70
  const hideAll = _.get(params, "hideAll", false);
58
71
  const noMetaData = _.get(params, "noMetaData", false);
59
72
  const noAttributeData = _.get(params, "noAttributeData", false);
60
73
  const hideDescriptionAndLinks = _.get(
61
74
  params,
62
75
  "hideDescriptionAndLinks",
63
- false
76
+ false,
64
77
  );
65
78
  const onlyLiveTechnologies = _.get(params, "onlyLiveTechnologies", false);
66
79
 
67
- const bwURL = constructBuiltWithURL("v14", {
80
+ const bwURL = constructBuiltWithURL("v15", {
68
81
  LOOKUP: url,
69
82
  HIDETEXT: hideAll,
70
83
  HIDEDL: hideDescriptionAndLinks,
71
84
  LIVEONLY: onlyLiveTechnologies,
72
85
  NOMETA: noMetaData,
73
- NOATTR: noAttributeData
86
+ NOATTR: noAttributeData,
74
87
  });
75
88
 
76
89
  const res = await utils.makeStandardRequest(bwURL, responseFormat);
@@ -85,7 +98,7 @@ function BuiltWith(apiKey, moduleParams = {}) {
85
98
  * @param {String} technology
86
99
  * @param {Object} params
87
100
  */
88
- lists: async function(technology, params) {
101
+ lists: async function (technology, params) {
89
102
  const includeMetaData = _.get(params, "includeMetaData", false);
90
103
  const offset = _.get(params, "offset");
91
104
  const since = _.get(params, "since");
@@ -94,11 +107,11 @@ function BuiltWith(apiKey, moduleParams = {}) {
94
107
  TECH: technology,
95
108
  META: includeMetaData,
96
109
  OFFSET: offset,
97
- SINCE: since
110
+ SINCE: since,
98
111
  });
99
112
 
100
- const res = await utils.makeBulletProofRequest(bwURL)
101
- return res
113
+ const res = await utils.makeBulletProofRequest(bwURL);
114
+ return res;
102
115
  },
103
116
 
104
117
  /**
@@ -107,11 +120,12 @@ function BuiltWith(apiKey, moduleParams = {}) {
107
120
  * @note Relationships API may throw an error related to the maxJSONLength property for certain URLs. This is thrown in BuiltWith and cannot be handled here.
108
121
  *
109
122
  * @see https://api.builtwith.com/relationships-api
110
- * @param {String} url
123
+ * @param {(string|string[])} url
111
124
  */
112
- relationships: async function(url) {
125
+ relationships: async function (url) {
126
+ checkUrlData(url);
113
127
  const bwURL = constructBuiltWithURL("rv1", {
114
- LOOKUP: url
128
+ LOOKUP: url,
115
129
  });
116
130
 
117
131
  const res = await utils.makeStandardRequest(bwURL, responseFormat);
@@ -123,14 +137,15 @@ function BuiltWith(apiKey, moduleParams = {}) {
123
137
  * Make a request to the BuiltWith Keywords API
124
138
  *
125
139
  * @see https://api.builtwith.com/keywords-api
126
- * @param {String} url
140
+ * @param {(string|string[])} url
127
141
  */
128
- keywords: async function(url) {
142
+ keywords: async function (url) {
143
+ checkUrlData(url);
129
144
  const bwURL = constructBuiltWithURL("kw2", {
130
- LOOKUP: url
145
+ LOOKUP: url,
131
146
  });
132
147
 
133
- const res = await utils.makeStandardRequest(bwURL, responseFormat)
148
+ const res = await utils.makeStandardRequest(bwURL, responseFormat);
134
149
  return res;
135
150
  },
136
151
 
@@ -141,16 +156,16 @@ function BuiltWith(apiKey, moduleParams = {}) {
141
156
  * @param {String} technology
142
157
  * @param {Object} params
143
158
  */
144
- trends: async function(technology, params) {
159
+ trends: async function (technology, params) {
145
160
  const date = _.get(params, "date");
146
161
 
147
162
  const bwURL = constructBuiltWithURL("trends/v6", {
148
163
  TECH: technology,
149
- DATE: date
164
+ DATE: date,
150
165
  });
151
166
 
152
167
  const res = await utils.makeBulletProofRequest(bwURL);
153
- return res
168
+ return res;
154
169
  },
155
170
 
156
171
  /**
@@ -160,7 +175,7 @@ function BuiltWith(apiKey, moduleParams = {}) {
160
175
  * @param {String} companyName
161
176
  * @param {Object} params
162
177
  */
163
- companyToUrl: async function(companyName, params) {
178
+ companyToUrl: async function (companyName, params) {
164
179
  const tld = _.get(params, "tld");
165
180
  const amount = _.get(params, "noMetaData");
166
181
 
@@ -169,12 +184,12 @@ function BuiltWith(apiKey, moduleParams = {}) {
169
184
  {
170
185
  COMPANY: encodeURIComponent(companyName),
171
186
  TLD: tld,
172
- AMOUNT: amount
187
+ AMOUNT: amount,
173
188
  },
174
- "ctu"
189
+ "ctu",
175
190
  );
176
191
 
177
- const res = await utils.makeStandardRequest(bwURL, responseFormat)
192
+ const res = await utils.makeStandardRequest(bwURL, responseFormat);
178
193
  return res;
179
194
  },
180
195
 
@@ -184,12 +199,12 @@ function BuiltWith(apiKey, moduleParams = {}) {
184
199
  * @see https://api.builtwith.com/domain-live-api
185
200
  * @param {String} url
186
201
  */
187
- domainLive: async function(url) {
188
- const bwURL = constructBuiltWithURL("dlv1", {
189
- LOOKUP: url
202
+ domainLive: async function (url) {
203
+ const bwURL = constructBuiltWithURL("ddlv2", {
204
+ LOOKUP: url,
190
205
  });
191
206
 
192
- const res = await utils.makeStandardRequest(bwURL, responseFormat)
207
+ const res = await utils.makeStandardRequest(bwURL, responseFormat);
193
208
  return res;
194
209
  },
195
210
 
@@ -200,28 +215,30 @@ function BuiltWith(apiKey, moduleParams = {}) {
200
215
  * @param {String} url
201
216
  * @param {Object} params
202
217
  */
203
- trust: async function(url, params) {
204
- const words = _.get(params, "words", "")
205
- const live = _.get(params, "live", false)
218
+ trust: async function (url, params) {
219
+ const words = _.get(params, "words", "");
220
+ const live = _.get(params, "live", false);
206
221
 
207
222
  const bwURL = constructBuiltWithURL("trustv1", {
208
223
  LOOKUP: url,
209
224
  // 'wordOne, wordTwo' ==> 'wordOne,wordTwo'
210
- WORDS: words.split(',').map(wrd => wrd.trim()).join(','),
211
- LIVE: live
225
+ WORDS: words
226
+ .split(",")
227
+ .map((wrd) => wrd.trim())
228
+ .join(","),
229
+ LIVE: live,
212
230
  });
213
231
 
214
- const res = await utils.makeStandardRequest(bwURL, responseFormat)
232
+ const res = await utils.makeStandardRequest(bwURL, responseFormat);
215
233
  return res;
216
234
  },
217
-
218
235
  };
219
236
  }
220
237
 
221
238
  // Constructor to authenticate and get module
222
- module.exports = function(apiKey, moduleParams) {
239
+ module.exports = function (apiKey, moduleParams) {
223
240
  if (!apiKey) {
224
- throw new Error('You must initialize the BuiltWith module with an api key')
241
+ throw new Error("You must initialize the BuiltWith module with an api key");
225
242
  }
226
- return BuiltWith(apiKey, moduleParams)
227
- }
243
+ return BuiltWith(apiKey, moduleParams);
244
+ };
@@ -0,0 +1,90 @@
1
+ const nock = require('nock');
2
+ const BuiltWith = require('../src/index');
3
+
4
+ const apiKey = 'testApiKey';
5
+ const moduleParams = { isBulletProof: false };
6
+
7
+ describe('BuiltWith', () => {
8
+ beforeEach(() => {
9
+ nock('https://api.builtwith.com')
10
+ .get(/.*/)
11
+ .reply(200, { test: 'data' });
12
+ });
13
+
14
+ afterEach(() => {
15
+ nock.cleanAll();
16
+ });
17
+
18
+ it('should make a standard request for the domain API', async () => {
19
+ const bw = BuiltWith(apiKey, moduleParams);
20
+
21
+ const response = await bw.domain('testUrl');
22
+
23
+ expect(response).toEqual({ test: 'data' });
24
+ });
25
+
26
+ it('should make a standard request for the lists API', async () => {
27
+ const bw = BuiltWith(apiKey, moduleParams);
28
+
29
+ const response = await bw.lists('testUrl');
30
+
31
+ expect(response).toEqual({ test: 'data' });
32
+ });
33
+
34
+ it('should make a standard request for the relationships API', async () => {
35
+ const bw = BuiltWith(apiKey, moduleParams);
36
+
37
+ const response = await bw.relationships('testUrl');
38
+
39
+ expect(response).toEqual({ test: 'data' });
40
+ });
41
+
42
+
43
+ it('should make a standard request for the free API', async () => {
44
+ const bw = BuiltWith(apiKey, moduleParams);
45
+
46
+ const response = await bw.free('testUrl');
47
+
48
+ expect(response).toEqual({ test: 'data' });
49
+ });
50
+
51
+ it('should make a standard request for the keywords API', async () => {
52
+ const bw = BuiltWith(apiKey, moduleParams);
53
+
54
+ const response = await bw.keywords('testUrl');
55
+
56
+ expect(response).toEqual({ test: 'data' });
57
+ });
58
+
59
+ it('should make a standard request for the trends API', async () => {
60
+ const bw = BuiltWith(apiKey, moduleParams);
61
+
62
+ const response = await bw.trends('testUrl');
63
+
64
+ expect(response).toEqual({ test: 'data' });
65
+ });
66
+
67
+ it('should make a standard request for the companyToUrl API', async () => {
68
+ const bw = BuiltWith(apiKey, moduleParams);
69
+
70
+ const response = await bw.companyToUrl('My Company');
71
+
72
+ expect(response).toEqual({ test: 'data' });
73
+ });
74
+
75
+ it('should make a standard request for the domainLive API', async () => {
76
+ const bw = BuiltWith(apiKey, moduleParams);
77
+
78
+ const response = await bw.domainLive('testUrl');
79
+
80
+ expect(response).toEqual({ test: 'data' });
81
+ });
82
+
83
+ it('should make a standard request for the trust API', async () => {
84
+ const bw = BuiltWith(apiKey, moduleParams);
85
+
86
+ const response = await bw.trust('testUrl');
87
+
88
+ expect(response).toEqual({ test: 'data' });
89
+ });
90
+ });
package/src/utils.js CHANGED
@@ -1,18 +1,16 @@
1
- const fetch = require("node-fetch")
2
- const { VALID_RESPONSE_TYPES } = require("./config")
1
+ const { VALID_RESPONSE_TYPES } = require("./config");
3
2
 
4
3
  module.exports = {
5
- makeStandardRequest: async function(url, responseFormat) {
6
- return fetch(url).then(res => {
7
- if (responseFormat === VALID_RESPONSE_TYPES.XML) {
8
- return res.text();
9
- } else {
10
- return res.json();
11
- }
12
- });
4
+ makeStandardRequest: async function (url, responseFormat) {
5
+ const res = await fetch(url);
6
+ if (responseFormat === VALID_RESPONSE_TYPES.XML) {
7
+ return res.text();
8
+ } else {
9
+ return res.json();
10
+ }
13
11
  },
14
12
 
15
- makeBulletProofRequest: async function(url, responseFormat) {
13
+ makeBulletProofRequest: async function (url, responseFormat) {
16
14
  const res = await fetch(url);
17
15
  if (
18
16
  responseFormat === VALID_RESPONSE_TYPES.TXT ||
@@ -29,7 +27,7 @@ module.exports = {
29
27
  return JSON.parse(parsed);
30
28
  } catch (e) {
31
29
  console.warn(
32
- "BuiltWith sent an invalid JSON payload. Falling back to text parsing."
30
+ "BuiltWith sent an invalid JSON payload. Falling back to text parsing.",
33
31
  );
34
32
  return parsed;
35
33
  }
@@ -41,7 +39,7 @@ module.exports = {
41
39
  * { paramOne: 'hello', paramTwo: 'goodbye' }
42
40
  * @param {Object} params
43
41
  */
44
- paramsObjToQueryString: function(params) {
42
+ paramsObjToQueryString: function (params) {
45
43
  // '&paramOne=hello&paramTwo=goodbye
46
44
  return Object.entries(params) // [['paramOne', 'hello'], ['paramTwo', 'goodbye]]
47
45
  .filter(([, value]) => {
@@ -52,5 +50,5 @@ module.exports = {
52
50
  return `${key}=${value}`; // ['paramOne=hello', 'paramTwo=goodbye']
53
51
  })
54
52
  .join("&"); // 'paramOne=hello&paramTwo=goodBye'
55
- }
56
- }
53
+ },
54
+ };