builtwith-api 1.0.5 → 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
@@ -18,13 +27,14 @@ APIS
18
27
  - trends
19
28
  - companyToUrl
20
29
  - domainLive
30
+ - trust
21
31
 
22
32
  ________________
23
33
 
24
34
  ## How To Use
25
35
 
26
36
  ```js
27
- const builtwith = require('builtwith')
37
+ const BuiltWith = require('builtwith-api')
28
38
 
29
39
  const builtwith = BuiltWith(process.env.YOUR_BUILTWITH_API_KEY, {
30
40
  responseFormat: 'json' // 'json' 'xml' 'txt' (only for lists API)
@@ -60,7 +70,9 @@ await builtwith.lists(technology, {
60
70
 
61
71
  await builtwith.relationships(url)
62
72
 
63
- 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)
64
76
 
65
77
  await builtwith.trends(technology, {
66
78
  // Totals will be the closest to this date - providing the ability to get historical totals
@@ -76,6 +88,13 @@ await builtwith.companyToUrl(companyName, {
76
88
  })
77
89
 
78
90
  await builtwith.domainLive(url)
91
+
92
+ await builtwith.trust(url, {
93
+ // If the words specified here are in the HTML of the website the result will have Stopwords set to true for LIVE lookups.
94
+ words: 'medicine,masks',
95
+ // Performs a live lookup of the website in question. This slows down the response. A result with a status of 'needLive' requires the LIVE option to determine if the website is suspect or not. Live lookups slow down the response of the API, you should consider calling this if the non-LIVE lookup response status is 'needLive'.
96
+ live: false
97
+ })
79
98
  ```
80
99
 
81
100
  Made live on Facebook by Zach Caceres during Covid-19 Quarantine
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "builtwith-api",
3
- "version": "1.0.5",
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,21 +199,46 @@ 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
+ },
210
+
211
+ /**
212
+ * Make a request to the BuiltWith Domain Live API
213
+ *
214
+ * @see https://api.builtwith.com/trust-api
215
+ * @param {String} url
216
+ * @param {Object} params
217
+ */
218
+ trust: async function (url, params) {
219
+ const words = _.get(params, "words", "");
220
+ const live = _.get(params, "live", false);
221
+
222
+ const bwURL = constructBuiltWithURL("trustv1", {
223
+ LOOKUP: url,
224
+ // 'wordOne, wordTwo' ==> 'wordOne,wordTwo'
225
+ WORDS: words
226
+ .split(",")
227
+ .map((wrd) => wrd.trim())
228
+ .join(","),
229
+ LIVE: live,
230
+ });
231
+
232
+ const res = await utils.makeStandardRequest(bwURL, responseFormat);
233
+ return res;
234
+ },
195
235
  };
196
236
  }
197
237
 
198
238
  // Constructor to authenticate and get module
199
- module.exports = function(apiKey, moduleParams) {
239
+ module.exports = function (apiKey, moduleParams) {
200
240
  if (!apiKey) {
201
- 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");
202
242
  }
203
- return BuiltWith(apiKey, moduleParams)
204
- }
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
+ };