builtwith-api 3.1.0 → 3.2.1
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/dist/cli.js +191 -103
- package/dist/cli.js.map +10 -9
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +162 -0
- package/dist/commands.js.map +10 -0
- package/dist/format.d.ts +2 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/index.d.ts +27 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -49
- package/dist/index.js.map +6 -6
- package/dist/params.d.ts.map +1 -1
- package/dist/request.d.ts +1 -1
- package/dist/request.d.ts.map +1 -1
- package/dist/schemas.d.ts +182 -36
- package/dist/schemas.d.ts.map +1 -1
- package/package.json +15 -22
- package/LICENSE +0 -21
- package/README.md +0 -249
- package/dist/config.js +0 -11
- package/dist/config.js.map +0 -1
- package/dist/mcp.d.ts +0 -3
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -689
- package/dist/mcp.js.map +0 -17
- package/dist/params.js +0 -37
- package/dist/params.js.map +0 -1
- package/dist/request.js +0 -39
- package/dist/request.js.map +0 -1
- package/dist/types.d.ts +0 -48
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,7 @@ var ResponseFormatSchema = z.enum(["xml", "json", "txt", "csv", "tsv"]);
|
|
|
15
15
|
var ClientOptionsSchema = z.strictObject({
|
|
16
16
|
responseFormat: ResponseFormatSchema.optional()
|
|
17
17
|
});
|
|
18
|
+
var dateRangePattern = /^\d{4}-\d{2}-\d{2}(-\d{4}-\d{2}-\d{2})?$/;
|
|
18
19
|
var DomainParamsSchema = z.strictObject({
|
|
19
20
|
hideAll: z.boolean().optional(),
|
|
20
21
|
hideDescriptionAndLinks: z.boolean().optional(),
|
|
@@ -22,8 +23,8 @@ var DomainParamsSchema = z.strictObject({
|
|
|
22
23
|
noMetaData: z.boolean().optional(),
|
|
23
24
|
noAttributeData: z.boolean().optional(),
|
|
24
25
|
noPII: z.boolean().optional(),
|
|
25
|
-
firstDetectedRange: z.string().optional(),
|
|
26
|
-
lastDetectedRange: z.string().optional()
|
|
26
|
+
firstDetectedRange: z.string().regex(dateRangePattern, "Expected YYYY-MM-DD or YYYY-MM-DD-YYYY-MM-DD").optional(),
|
|
27
|
+
lastDetectedRange: z.string().regex(dateRangePattern, "Expected YYYY-MM-DD or YYYY-MM-DD-YYYY-MM-DD").optional()
|
|
27
28
|
});
|
|
28
29
|
var ListsParamsSchema = z.strictObject({
|
|
29
30
|
includeMetaData: z.boolean().optional(),
|
|
@@ -42,21 +43,18 @@ var TrustParamsSchema = z.strictObject({
|
|
|
42
43
|
live: z.boolean().optional()
|
|
43
44
|
});
|
|
44
45
|
var SingleLookupSchema = z.string().min(1);
|
|
45
|
-
var MultiLookupSchema = z.union([
|
|
46
|
-
|
|
47
|
-
z.array(z.string().min(1)).min(1).max(16)
|
|
48
|
-
]);
|
|
49
|
-
var FreeResponseSchema = z.object({
|
|
46
|
+
var MultiLookupSchema = z.union([z.string().min(1), z.array(z.string().min(1)).min(1).max(16)]);
|
|
47
|
+
var FreeResponseSchema = z.strictObject({
|
|
50
48
|
domain: z.string(),
|
|
51
49
|
first: z.number(),
|
|
52
50
|
last: z.number(),
|
|
53
|
-
groups: z.array(z.
|
|
51
|
+
groups: z.array(z.strictObject({
|
|
54
52
|
name: z.string(),
|
|
55
53
|
live: z.number(),
|
|
56
54
|
dead: z.number(),
|
|
57
55
|
latest: z.number(),
|
|
58
56
|
oldest: z.number(),
|
|
59
|
-
categories: z.array(z.
|
|
57
|
+
categories: z.array(z.strictObject({
|
|
60
58
|
live: z.number(),
|
|
61
59
|
dead: z.number(),
|
|
62
60
|
latest: z.number(),
|
|
@@ -65,7 +63,7 @@ var FreeResponseSchema = z.object({
|
|
|
65
63
|
}))
|
|
66
64
|
}))
|
|
67
65
|
});
|
|
68
|
-
var TechnologySchema = z.
|
|
66
|
+
var TechnologySchema = z.strictObject({
|
|
69
67
|
Name: z.string(),
|
|
70
68
|
Description: z.string(),
|
|
71
69
|
Link: z.string(),
|
|
@@ -76,7 +74,7 @@ var TechnologySchema = z.object({
|
|
|
76
74
|
IsPremium: z.string(),
|
|
77
75
|
Categories: z.array(z.string()).optional()
|
|
78
76
|
});
|
|
79
|
-
var PathSchema = z.
|
|
77
|
+
var PathSchema = z.strictObject({
|
|
80
78
|
Technologies: z.array(TechnologySchema),
|
|
81
79
|
FirstIndexed: z.number(),
|
|
82
80
|
LastIndexed: z.number(),
|
|
@@ -84,7 +82,7 @@ var PathSchema = z.object({
|
|
|
84
82
|
Url: z.string(),
|
|
85
83
|
SubDomain: z.string()
|
|
86
84
|
});
|
|
87
|
-
var MetaSchema = z.
|
|
85
|
+
var MetaSchema = z.strictObject({
|
|
88
86
|
Majestic: z.number(),
|
|
89
87
|
Vertical: z.string(),
|
|
90
88
|
Social: z.array(z.string()),
|
|
@@ -95,7 +93,7 @@ var MetaSchema = z.object({
|
|
|
95
93
|
State: z.string(),
|
|
96
94
|
Postcode: z.string(),
|
|
97
95
|
Country: z.string(),
|
|
98
|
-
Names: z.array(z.
|
|
96
|
+
Names: z.array(z.strictObject({
|
|
99
97
|
Name: z.string(),
|
|
100
98
|
Type: z.number(),
|
|
101
99
|
Level: z.string(),
|
|
@@ -104,7 +102,7 @@ var MetaSchema = z.object({
|
|
|
104
102
|
ARank: z.number(),
|
|
105
103
|
QRank: z.number()
|
|
106
104
|
});
|
|
107
|
-
var AttributesSchema = z.
|
|
105
|
+
var AttributesSchema = z.strictObject({
|
|
108
106
|
MJRank: z.number(),
|
|
109
107
|
MJTLDRank: z.number(),
|
|
110
108
|
RefSN: z.number(),
|
|
@@ -116,12 +114,15 @@ var AttributesSchema = z.object({
|
|
|
116
114
|
AdobeTags: z.number(),
|
|
117
115
|
CDimensions: z.number(),
|
|
118
116
|
CGoals: z.number(),
|
|
119
|
-
CMetrics: z.number()
|
|
117
|
+
CMetrics: z.number(),
|
|
118
|
+
Followers: z.number(),
|
|
119
|
+
Employees: z.number(),
|
|
120
|
+
ProductCount: z.number().optional()
|
|
120
121
|
});
|
|
121
|
-
var DomainResponseSchema = z.
|
|
122
|
-
Results: z.array(z.
|
|
123
|
-
Result: z.
|
|
124
|
-
SpendHistory: z.array(z.
|
|
122
|
+
var DomainResponseSchema = z.strictObject({
|
|
123
|
+
Results: z.array(z.strictObject({
|
|
124
|
+
Result: z.strictObject({
|
|
125
|
+
SpendHistory: z.array(z.strictObject({
|
|
125
126
|
D: z.number(),
|
|
126
127
|
S: z.number()
|
|
127
128
|
})),
|
|
@@ -138,9 +139,9 @@ var DomainResponseSchema = z.object({
|
|
|
138
139
|
})),
|
|
139
140
|
Errors: z.array(z.string())
|
|
140
141
|
});
|
|
141
|
-
var ListsResponseSchema = z.
|
|
142
|
+
var ListsResponseSchema = z.strictObject({
|
|
142
143
|
NextOffset: z.string(),
|
|
143
|
-
Results: z.array(z.
|
|
144
|
+
Results: z.array(z.strictObject({
|
|
144
145
|
D: z.string(),
|
|
145
146
|
FI: z.number().optional(),
|
|
146
147
|
LI: z.number().optional(),
|
|
@@ -159,15 +160,15 @@ var ListsResponseSchema = z.object({
|
|
|
159
160
|
Country: z.string().optional()
|
|
160
161
|
}))
|
|
161
162
|
});
|
|
162
|
-
var RelationshipsResponseSchema = z.
|
|
163
|
-
Relationships: z.array(z.
|
|
163
|
+
var RelationshipsResponseSchema = z.strictObject({
|
|
164
|
+
Relationships: z.array(z.strictObject({
|
|
164
165
|
Domain: z.string(),
|
|
165
|
-
Identifiers: z.array(z.
|
|
166
|
+
Identifiers: z.array(z.strictObject({
|
|
166
167
|
Value: z.string(),
|
|
167
168
|
Type: z.string(),
|
|
168
169
|
First: z.number(),
|
|
169
170
|
Last: z.number(),
|
|
170
|
-
Matches: z.array(z.
|
|
171
|
+
Matches: z.array(z.strictObject({
|
|
171
172
|
Domain: z.string(),
|
|
172
173
|
First: z.number(),
|
|
173
174
|
Last: z.number(),
|
|
@@ -181,14 +182,14 @@ var RelationshipsResponseSchema = z.object({
|
|
|
181
182
|
next_skip: z.number(),
|
|
182
183
|
more_results: z.boolean()
|
|
183
184
|
});
|
|
184
|
-
var KeywordsResponseSchema = z.
|
|
185
|
-
Keywords: z.array(z.
|
|
185
|
+
var KeywordsResponseSchema = z.strictObject({
|
|
186
|
+
Keywords: z.array(z.strictObject({
|
|
186
187
|
Domain: z.string(),
|
|
187
188
|
Keywords: z.array(z.string())
|
|
188
189
|
}))
|
|
189
190
|
});
|
|
190
|
-
var TrendsResponseSchema = z.
|
|
191
|
-
Tech: z.
|
|
191
|
+
var TrendsResponseSchema = z.strictObject({
|
|
192
|
+
Tech: z.strictObject({
|
|
192
193
|
icon: z.string(),
|
|
193
194
|
categories: z.array(z.string()),
|
|
194
195
|
tag: z.string(),
|
|
@@ -197,7 +198,7 @@ var TrendsResponseSchema = z.object({
|
|
|
197
198
|
description: z.string(),
|
|
198
199
|
link: z.string(),
|
|
199
200
|
trends_link: z.string(),
|
|
200
|
-
coverage: z.
|
|
201
|
+
coverage: z.strictObject({
|
|
201
202
|
ten_k: z.number(),
|
|
202
203
|
hundred_k: z.number(),
|
|
203
204
|
milly: z.number(),
|
|
@@ -206,7 +207,7 @@ var TrendsResponseSchema = z.object({
|
|
|
206
207
|
})
|
|
207
208
|
})
|
|
208
209
|
});
|
|
209
|
-
var CompanyToUrlResponseSchema = z.array(z.
|
|
210
|
+
var CompanyToUrlResponseSchema = z.array(z.strictObject({
|
|
210
211
|
Domain: z.string(),
|
|
211
212
|
CompanyName: z.string(),
|
|
212
213
|
Spend: z.number(),
|
|
@@ -219,9 +220,9 @@ var CompanyToUrlResponseSchema = z.array(z.object({
|
|
|
219
220
|
City: z.string(),
|
|
220
221
|
Socials: z.array(z.string())
|
|
221
222
|
}));
|
|
222
|
-
var TrustResponseSchema = z.
|
|
223
|
+
var TrustResponseSchema = z.strictObject({
|
|
223
224
|
Domain: z.string(),
|
|
224
|
-
DBRecord: z.
|
|
225
|
+
DBRecord: z.strictObject({
|
|
225
226
|
EarliestRecord: z.number(),
|
|
226
227
|
LatestUpdate: z.number(),
|
|
227
228
|
PremiumTechs: z.number(),
|
|
@@ -237,18 +238,18 @@ var TrustResponseSchema = z.object({
|
|
|
237
238
|
LiveRecord: z.object({}).passthrough().nullable(),
|
|
238
239
|
Status: z.number()
|
|
239
240
|
});
|
|
240
|
-
var TagsResponseSchema = z.array(z.
|
|
241
|
+
var TagsResponseSchema = z.array(z.strictObject({
|
|
241
242
|
Value: z.string(),
|
|
242
|
-
Matches: z.array(z.
|
|
243
|
+
Matches: z.array(z.strictObject({
|
|
243
244
|
Domain: z.string(),
|
|
244
245
|
First: z.string(),
|
|
245
246
|
Last: z.string()
|
|
246
247
|
}))
|
|
247
248
|
}));
|
|
248
|
-
var RecommendationsResponseSchema = z.array(z.
|
|
249
|
+
var RecommendationsResponseSchema = z.array(z.strictObject({
|
|
249
250
|
Domain: z.string(),
|
|
250
251
|
Compiled: z.string(),
|
|
251
|
-
Recommendations: z.array(z.
|
|
252
|
+
Recommendations: z.array(z.strictObject({
|
|
252
253
|
link: z.string(),
|
|
253
254
|
name: z.string(),
|
|
254
255
|
tag: z.string(),
|
|
@@ -257,20 +258,20 @@ var RecommendationsResponseSchema = z.array(z.object({
|
|
|
257
258
|
match: z.number()
|
|
258
259
|
}))
|
|
259
260
|
}));
|
|
260
|
-
var RedirectsResponseSchema = z.
|
|
261
|
+
var RedirectsResponseSchema = z.strictObject({
|
|
261
262
|
Lookup: z.string(),
|
|
262
|
-
Inbound: z.array(z.
|
|
263
|
+
Inbound: z.array(z.strictObject({
|
|
263
264
|
Domain: z.string(),
|
|
264
265
|
FirstDetected: z.string(),
|
|
265
266
|
LastDetected: z.string()
|
|
266
267
|
})),
|
|
267
|
-
Outbound: z.array(z.
|
|
268
|
+
Outbound: z.array(z.strictObject({
|
|
268
269
|
Domain: z.string(),
|
|
269
270
|
FirstDetected: z.string(),
|
|
270
271
|
LastDetected: z.string()
|
|
271
272
|
}))
|
|
272
273
|
});
|
|
273
|
-
var ProductResponseSchema = z.
|
|
274
|
+
var ProductResponseSchema = z.strictObject({
|
|
274
275
|
query: z.string(),
|
|
275
276
|
is_more: z.boolean(),
|
|
276
277
|
page: z.number(),
|
|
@@ -282,9 +283,9 @@ var ProductResponseSchema = z.object({
|
|
|
282
283
|
remaining: z.number(),
|
|
283
284
|
used_this_query: z.number(),
|
|
284
285
|
next_page: z.string(),
|
|
285
|
-
shops: z.array(z.
|
|
286
|
+
shops: z.array(z.strictObject({
|
|
286
287
|
Domain: z.string(),
|
|
287
|
-
Products: z.array(z.
|
|
288
|
+
Products: z.array(z.strictObject({
|
|
288
289
|
Title: z.string(),
|
|
289
290
|
Url: z.string(),
|
|
290
291
|
Indexed: z.string(),
|
|
@@ -299,10 +300,7 @@ var ProductResponseSchema = z.object({
|
|
|
299
300
|
// src/params.ts
|
|
300
301
|
var toQueryString = (params) => Object.entries(params).filter((entry) => entry[1] !== undefined).map(([k, v]) => `${k}=${encodeURIComponent(v).replace(/%2C/gi, ",")}`).join("&");
|
|
301
302
|
var booleanFlag = (value) => value ? "yes" : undefined;
|
|
302
|
-
var booleanParams = (params, mapping) => Object.fromEntries(Object.entries(mapping).map(([jsKey, apiKey]) => [
|
|
303
|
-
apiKey,
|
|
304
|
-
booleanFlag(params?.[jsKey])
|
|
305
|
-
]));
|
|
303
|
+
var booleanParams = (params, mapping) => Object.fromEntries(Object.entries(mapping).map(([jsKey, apiKey]) => [apiKey, booleanFlag(params?.[jsKey])]));
|
|
306
304
|
var cleanWords = (words) => words ? words.split(",").map((w) => w.trim()).join(",") : undefined;
|
|
307
305
|
var buildURL = (apiKey, format, path, params, subdomain = "api") => {
|
|
308
306
|
const base = `https://${subdomain}.builtwith.com/${path}/api.${format}?KEY=${apiKey}`;
|
|
@@ -324,12 +322,23 @@ var validateLookup = (url, { multi = false } = {}) => {
|
|
|
324
322
|
};
|
|
325
323
|
|
|
326
324
|
// src/request.ts
|
|
325
|
+
import { z as z2 } from "zod/v4";
|
|
327
326
|
var TEXT_FORMATS = [
|
|
328
327
|
VALID_RESPONSE_TYPES.TXT,
|
|
329
328
|
VALID_RESPONSE_TYPES.XML,
|
|
330
329
|
VALID_RESPONSE_TYPES.CSV,
|
|
331
330
|
VALID_RESPONSE_TYPES.TSV
|
|
332
331
|
];
|
|
332
|
+
var ApiErrorSchema = z2.object({
|
|
333
|
+
Errors: z2.array(z2.object({ Message: z2.string() }))
|
|
334
|
+
});
|
|
335
|
+
function checkForApiError(data) {
|
|
336
|
+
const parsed = ApiErrorSchema.safeParse(data);
|
|
337
|
+
if (parsed.success && parsed.data.Errors.length > 0) {
|
|
338
|
+
const messages = parsed.data.Errors.map((e) => e.Message).join("; ");
|
|
339
|
+
throw new Error(`BuiltWith API error: ${messages}`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
333
342
|
var request = async (url, format, schema) => {
|
|
334
343
|
const res = await fetch(url);
|
|
335
344
|
if (!res.ok) {
|
|
@@ -339,7 +348,14 @@ var request = async (url, format, schema) => {
|
|
|
339
348
|
if (TEXT_FORMATS.includes(format)) {
|
|
340
349
|
return res.text();
|
|
341
350
|
}
|
|
342
|
-
const
|
|
351
|
+
const raw = await res.text();
|
|
352
|
+
let data;
|
|
353
|
+
try {
|
|
354
|
+
data = JSON.parse(raw);
|
|
355
|
+
} catch {
|
|
356
|
+
throw new Error(`BuiltWith returned invalid JSON: ${raw.slice(0, 200)}`);
|
|
357
|
+
}
|
|
358
|
+
checkForApiError(data);
|
|
343
359
|
return schema.parse(data);
|
|
344
360
|
};
|
|
345
361
|
var requestSafe = async (url, format, schema) => {
|
|
@@ -359,6 +375,7 @@ var requestSafe = async (url, format, schema) => {
|
|
|
359
375
|
console.warn("BuiltWith sent an invalid JSON payload. Falling back to text parsing.");
|
|
360
376
|
return raw;
|
|
361
377
|
}
|
|
378
|
+
checkForApiError(data);
|
|
362
379
|
return schema.parse(data);
|
|
363
380
|
};
|
|
364
381
|
|
|
@@ -470,28 +487,6 @@ function createClient(apiKey, moduleParams = {}) {
|
|
|
470
487
|
};
|
|
471
488
|
}
|
|
472
489
|
|
|
473
|
-
// src/errors.ts
|
|
474
|
-
import { z as z2 } from "zod/v4";
|
|
475
|
-
function formatError(err) {
|
|
476
|
-
if (err instanceof z2.ZodError) {
|
|
477
|
-
const fields = err.issues.map((i) => {
|
|
478
|
-
const path = i.path.length > 0 ? i.path.join(".") : "response";
|
|
479
|
-
return ` ${path}: ${i.message}`;
|
|
480
|
-
});
|
|
481
|
-
return `BuiltWith API returned an unexpected response:
|
|
482
|
-
${fields.join(`
|
|
483
|
-
`)}`;
|
|
484
|
-
}
|
|
485
|
-
if (err instanceof Error) {
|
|
486
|
-
return err.message;
|
|
487
|
-
}
|
|
488
|
-
return String(err);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// src/cli.ts
|
|
492
|
-
import { createRequire } from "node:module";
|
|
493
|
-
import { parseArgs } from "node:util";
|
|
494
|
-
|
|
495
490
|
// src/commands.ts
|
|
496
491
|
function splitLookup(value) {
|
|
497
492
|
const str = String(value);
|
|
@@ -501,23 +496,36 @@ var commands = [
|
|
|
501
496
|
{
|
|
502
497
|
name: "free",
|
|
503
498
|
description: "Free lookup — basic technology profile for a domain",
|
|
504
|
-
args: [
|
|
505
|
-
{ name: "lookup", description: "Domain to look up", type: "string", required: true }
|
|
506
|
-
],
|
|
499
|
+
args: [{ name: "lookup", description: "Domain to look up", type: "string", required: true }],
|
|
507
500
|
execute: (client, args) => client.free(String(args.lookup))
|
|
508
501
|
},
|
|
509
502
|
{
|
|
510
503
|
name: "domain",
|
|
511
504
|
description: "Detailed technology profile for one or more domains (comma-separated)",
|
|
512
505
|
args: [
|
|
513
|
-
{
|
|
506
|
+
{
|
|
507
|
+
name: "lookup",
|
|
508
|
+
description: "Domain(s) to look up (comma-separated for multiple)",
|
|
509
|
+
type: "string",
|
|
510
|
+
required: true
|
|
511
|
+
},
|
|
514
512
|
{ name: "hideAll", description: "Hide description text and links", type: "boolean", required: false },
|
|
515
|
-
{
|
|
513
|
+
{
|
|
514
|
+
name: "hideDescriptionAndLinks",
|
|
515
|
+
description: "Hide description and links only",
|
|
516
|
+
type: "boolean",
|
|
517
|
+
required: false
|
|
518
|
+
},
|
|
516
519
|
{ name: "onlyLiveTechnologies", description: "Only return live technologies", type: "boolean", required: false },
|
|
517
520
|
{ name: "noMetaData", description: "Exclude metadata", type: "boolean", required: false },
|
|
518
521
|
{ name: "noAttributeData", description: "Exclude attribute data", type: "boolean", required: false },
|
|
519
522
|
{ name: "noPII", description: "Exclude personally identifiable information", type: "boolean", required: false },
|
|
520
|
-
{
|
|
523
|
+
{
|
|
524
|
+
name: "firstDetectedRange",
|
|
525
|
+
description: "Filter by first detected date range",
|
|
526
|
+
type: "string",
|
|
527
|
+
required: false
|
|
528
|
+
},
|
|
521
529
|
{ name: "lastDetectedRange", description: "Filter by last detected date range", type: "string", required: false }
|
|
522
530
|
],
|
|
523
531
|
execute: (client, args) => {
|
|
@@ -544,7 +552,12 @@ var commands = [
|
|
|
544
552
|
name: "relationships",
|
|
545
553
|
description: "Find related domains via shared identifiers",
|
|
546
554
|
args: [
|
|
547
|
-
{
|
|
555
|
+
{
|
|
556
|
+
name: "lookup",
|
|
557
|
+
description: "Domain(s) to look up (comma-separated for multiple)",
|
|
558
|
+
type: "string",
|
|
559
|
+
required: true
|
|
560
|
+
}
|
|
548
561
|
],
|
|
549
562
|
execute: (client, args) => client.relationships(splitLookup(args.lookup))
|
|
550
563
|
},
|
|
@@ -552,7 +565,12 @@ var commands = [
|
|
|
552
565
|
name: "keywords",
|
|
553
566
|
description: "Get keywords for one or more domains",
|
|
554
567
|
args: [
|
|
555
|
-
{
|
|
568
|
+
{
|
|
569
|
+
name: "lookup",
|
|
570
|
+
description: "Domain(s) to look up (comma-separated for multiple)",
|
|
571
|
+
type: "string",
|
|
572
|
+
required: true
|
|
573
|
+
}
|
|
556
574
|
],
|
|
557
575
|
execute: (client, args) => client.keywords(splitLookup(args.lookup))
|
|
558
576
|
},
|
|
@@ -584,9 +602,7 @@ var commands = [
|
|
|
584
602
|
{
|
|
585
603
|
name: "domainLive",
|
|
586
604
|
description: "Live technology lookup for a domain",
|
|
587
|
-
args: [
|
|
588
|
-
{ name: "lookup", description: "Domain to look up", type: "string", required: true }
|
|
589
|
-
],
|
|
605
|
+
args: [{ name: "lookup", description: "Domain to look up", type: "string", required: true }],
|
|
590
606
|
execute: (client, args) => client.domainLive(String(args.lookup))
|
|
591
607
|
},
|
|
592
608
|
{
|
|
@@ -605,37 +621,91 @@ var commands = [
|
|
|
605
621
|
{
|
|
606
622
|
name: "tags",
|
|
607
623
|
description: "Get tracking/analytics tags for a domain",
|
|
608
|
-
args: [
|
|
609
|
-
{ name: "lookup", description: "Domain to look up", type: "string", required: true }
|
|
610
|
-
],
|
|
624
|
+
args: [{ name: "lookup", description: "Domain to look up", type: "string", required: true }],
|
|
611
625
|
execute: (client, args) => client.tags(String(args.lookup))
|
|
612
626
|
},
|
|
613
627
|
{
|
|
614
628
|
name: "recommendations",
|
|
615
629
|
description: "Get technology recommendations for a domain",
|
|
616
|
-
args: [
|
|
617
|
-
{ name: "lookup", description: "Domain to look up", type: "string", required: true }
|
|
618
|
-
],
|
|
630
|
+
args: [{ name: "lookup", description: "Domain to look up", type: "string", required: true }],
|
|
619
631
|
execute: (client, args) => client.recommendations(String(args.lookup))
|
|
620
632
|
},
|
|
621
633
|
{
|
|
622
634
|
name: "redirects",
|
|
623
635
|
description: "Get redirect chains for a domain",
|
|
624
|
-
args: [
|
|
625
|
-
{ name: "lookup", description: "Domain to look up", type: "string", required: true }
|
|
626
|
-
],
|
|
636
|
+
args: [{ name: "lookup", description: "Domain to look up", type: "string", required: true }],
|
|
627
637
|
execute: (client, args) => client.redirects(String(args.lookup))
|
|
628
638
|
},
|
|
629
639
|
{
|
|
630
640
|
name: "product",
|
|
631
641
|
description: "Search for products across e-commerce sites",
|
|
632
|
-
args: [
|
|
633
|
-
{ name: "query", description: "Product search query", type: "string", required: true }
|
|
634
|
-
],
|
|
642
|
+
args: [{ name: "query", description: "Product search query", type: "string", required: true }],
|
|
635
643
|
execute: (client, args) => client.product(String(args.query))
|
|
636
644
|
}
|
|
637
645
|
];
|
|
638
646
|
|
|
647
|
+
// src/errors.ts
|
|
648
|
+
import { z as z3 } from "zod/v4";
|
|
649
|
+
function formatError(err) {
|
|
650
|
+
if (err instanceof z3.ZodError) {
|
|
651
|
+
const fields = err.issues.map((i) => {
|
|
652
|
+
const path = i.path.length > 0 ? i.path.join(".") : "response";
|
|
653
|
+
return ` ${path}: ${i.message}`;
|
|
654
|
+
});
|
|
655
|
+
return `BuiltWith API returned an unexpected response:
|
|
656
|
+
${fields.join(`
|
|
657
|
+
`)}`;
|
|
658
|
+
}
|
|
659
|
+
if (err instanceof Error) {
|
|
660
|
+
return err.message;
|
|
661
|
+
}
|
|
662
|
+
return String(err);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// src/cli.ts
|
|
666
|
+
import { createRequire } from "node:module";
|
|
667
|
+
import { parseArgs } from "node:util";
|
|
668
|
+
|
|
669
|
+
// src/format.ts
|
|
670
|
+
function formatTable(data, indent = 0) {
|
|
671
|
+
const pad = " ".repeat(indent);
|
|
672
|
+
if (data === null || data === undefined)
|
|
673
|
+
return `${pad}(none)`;
|
|
674
|
+
if (typeof data !== "object")
|
|
675
|
+
return `${pad}${data}`;
|
|
676
|
+
if (Array.isArray(data)) {
|
|
677
|
+
if (data.length === 0)
|
|
678
|
+
return `${pad}(empty)`;
|
|
679
|
+
const allFlatObjects = data.every((item) => typeof item === "object" && item !== null && !Array.isArray(item) && Object.values(item).every((v) => v === null || typeof v !== "object"));
|
|
680
|
+
if (allFlatObjects) {
|
|
681
|
+
const keys = [...new Set(data.flatMap((item) => Object.keys(item)))];
|
|
682
|
+
if (keys.length === 0)
|
|
683
|
+
return `${pad}(${data.length} empty items)`;
|
|
684
|
+
const widths = keys.map((k) => Math.max(k.length, ...data.map((item) => String(item[k] ?? "").length)));
|
|
685
|
+
const header = keys.map((k, i) => k.padEnd(widths[i])).join(" ");
|
|
686
|
+
const separator = keys.map((_, i) => "─".repeat(widths[i])).join(" ");
|
|
687
|
+
const rows = data.map((item) => keys.map((k, i) => String(item[k] ?? "").padEnd(widths[i])).join(" "));
|
|
688
|
+
return [pad + header, pad + separator, ...rows.map((r) => pad + r)].join(`
|
|
689
|
+
`);
|
|
690
|
+
}
|
|
691
|
+
return data.map((item, i) => `${pad}[${i}]
|
|
692
|
+
${formatTable(item, indent + 1)}`).join(`
|
|
693
|
+
`);
|
|
694
|
+
}
|
|
695
|
+
const entries = Object.entries(data);
|
|
696
|
+
if (entries.length === 0)
|
|
697
|
+
return `${pad}(empty)`;
|
|
698
|
+
const maxKey = Math.max(...entries.map(([k]) => k.length));
|
|
699
|
+
return entries.map(([key, value]) => {
|
|
700
|
+
if (typeof value === "object" && value !== null) {
|
|
701
|
+
return `${pad}${key}:
|
|
702
|
+
${formatTable(value, indent + 1)}`;
|
|
703
|
+
}
|
|
704
|
+
return `${pad}${key.padEnd(maxKey)} ${value}`;
|
|
705
|
+
}).join(`
|
|
706
|
+
`);
|
|
707
|
+
}
|
|
708
|
+
|
|
639
709
|
// src/cli.ts
|
|
640
710
|
var require2 = createRequire(import.meta.url);
|
|
641
711
|
var { version } = require2("../package.json");
|
|
@@ -647,11 +717,13 @@ ${commands.map((c) => ` ${c.name.padEnd(16)} ${c.description}`).join(`
|
|
|
647
717
|
|
|
648
718
|
Options:
|
|
649
719
|
--api-key <key> BuiltWith API key (or set BUILTWITH_API_KEY env var)
|
|
720
|
+
--table Pretty-print output as a readable table instead of JSON
|
|
650
721
|
--version Show version number
|
|
651
722
|
--help Show help
|
|
652
723
|
|
|
653
724
|
Examples:
|
|
654
725
|
builtwith free example.com
|
|
726
|
+
builtwith free example.com --table
|
|
655
727
|
builtwith domain example.com --hideAll --onlyLiveTechnologies
|
|
656
728
|
builtwith domain "example.com,other.com"
|
|
657
729
|
builtwith lists Shopify --since 2024-01-01
|
|
@@ -669,11 +741,15 @@ function printCommandHelp(cmd) {
|
|
|
669
741
|
for (const f of flags) {
|
|
670
742
|
console.log(` --${f.name.padEnd(28)} ${f.description} (${f.type})`);
|
|
671
743
|
}
|
|
744
|
+
console.log();
|
|
672
745
|
}
|
|
746
|
+
console.log("Global options:");
|
|
747
|
+
console.log(` --api-key <key> BuiltWith API key (or set BUILTWITH_API_KEY env var)`);
|
|
748
|
+
console.log(` --table Pretty-print output as a readable table instead of JSON`);
|
|
673
749
|
}
|
|
674
750
|
function run() {
|
|
675
751
|
const argv = process.argv.slice(2);
|
|
676
|
-
if (argv
|
|
752
|
+
if (argv[0] === "--version" || argv[0] === "-V") {
|
|
677
753
|
console.log(version);
|
|
678
754
|
process.exit(0);
|
|
679
755
|
}
|
|
@@ -695,22 +771,30 @@ function run() {
|
|
|
695
771
|
}
|
|
696
772
|
const primaryArg = cmd.args.find((a) => a.required);
|
|
697
773
|
const primaryValue = argv[1];
|
|
698
|
-
if (primaryArg && (!primaryValue || primaryValue.startsWith("
|
|
774
|
+
if (primaryArg && (!primaryValue || primaryValue.startsWith("-"))) {
|
|
699
775
|
console.error(`Error: missing required argument <${primaryArg.name}>`);
|
|
700
776
|
process.exit(1);
|
|
701
777
|
}
|
|
702
778
|
const flagArgs = cmd.args.filter((a) => !a.required);
|
|
703
779
|
const options = {
|
|
704
|
-
"api-key": { type: "string" }
|
|
780
|
+
"api-key": { type: "string" },
|
|
781
|
+
table: { type: "boolean" }
|
|
705
782
|
};
|
|
706
783
|
for (const f of flagArgs) {
|
|
707
784
|
options[f.name] = { type: f.type === "boolean" ? "boolean" : "string" };
|
|
708
785
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
786
|
+
let values;
|
|
787
|
+
try {
|
|
788
|
+
({ values } = parseArgs({
|
|
789
|
+
args: argv.slice(2),
|
|
790
|
+
options,
|
|
791
|
+
strict: true
|
|
792
|
+
}));
|
|
793
|
+
} catch (err) {
|
|
794
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
795
|
+
process.exit(1);
|
|
796
|
+
}
|
|
797
|
+
const useTable = Boolean(values.table);
|
|
714
798
|
const apiKey = values["api-key"] || process.env.BUILTWITH_API_KEY;
|
|
715
799
|
if (!apiKey) {
|
|
716
800
|
console.error("Error: pass --api-key or set BUILTWITH_API_KEY environment variable.");
|
|
@@ -731,7 +815,11 @@ function run() {
|
|
|
731
815
|
}
|
|
732
816
|
const client = createClient(apiKey);
|
|
733
817
|
cmd.execute(client, args).then((result) => {
|
|
734
|
-
|
|
818
|
+
if (useTable) {
|
|
819
|
+
console.log(formatTable(result));
|
|
820
|
+
} else {
|
|
821
|
+
console.log(JSON.stringify(result, null, 2));
|
|
822
|
+
}
|
|
735
823
|
}).catch((err) => {
|
|
736
824
|
console.error(formatError(err));
|
|
737
825
|
process.exit(1);
|
|
@@ -739,4 +827,4 @@ function run() {
|
|
|
739
827
|
}
|
|
740
828
|
run();
|
|
741
829
|
|
|
742
|
-
//# debugId=
|
|
830
|
+
//# debugId=D6F1EBFA208B3E4B64756E2164756E21
|