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 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
- z.string().min(1),
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.object({
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.object({
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.object({
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.object({
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.object({
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.object({
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.object({
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.object({
122
- Results: z.array(z.object({
123
- Result: z.object({
124
- SpendHistory: z.array(z.object({
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.object({
142
+ var ListsResponseSchema = z.strictObject({
142
143
  NextOffset: z.string(),
143
- Results: z.array(z.object({
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.object({
163
- Relationships: z.array(z.object({
163
+ var RelationshipsResponseSchema = z.strictObject({
164
+ Relationships: z.array(z.strictObject({
164
165
  Domain: z.string(),
165
- Identifiers: z.array(z.object({
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.object({
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.object({
185
- Keywords: z.array(z.object({
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.object({
191
- Tech: z.object({
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.object({
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.object({
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.object({
223
+ var TrustResponseSchema = z.strictObject({
223
224
  Domain: z.string(),
224
- DBRecord: z.object({
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.object({
241
+ var TagsResponseSchema = z.array(z.strictObject({
241
242
  Value: z.string(),
242
- Matches: z.array(z.object({
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.object({
249
+ var RecommendationsResponseSchema = z.array(z.strictObject({
249
250
  Domain: z.string(),
250
251
  Compiled: z.string(),
251
- Recommendations: z.array(z.object({
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.object({
261
+ var RedirectsResponseSchema = z.strictObject({
261
262
  Lookup: z.string(),
262
- Inbound: z.array(z.object({
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.object({
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.object({
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.object({
286
+ shops: z.array(z.strictObject({
286
287
  Domain: z.string(),
287
- Products: z.array(z.object({
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 data = await res.json();
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
- { name: "lookup", description: "Domain(s) to look up (comma-separated for multiple)", type: "string", required: true },
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
- { name: "hideDescriptionAndLinks", description: "Hide description and links only", type: "boolean", required: false },
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
- { name: "firstDetectedRange", description: "Filter by first detected date range", type: "string", required: false },
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
- { name: "lookup", description: "Domain(s) to look up (comma-separated for multiple)", type: "string", required: true }
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
- { name: "lookup", description: "Domain(s) to look up (comma-separated for multiple)", type: "string", required: true }
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.includes("--version") || argv.includes("-V")) {
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
- const { values } = parseArgs({
710
- args: argv.slice(2),
711
- options,
712
- strict: false
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
- console.log(JSON.stringify(result, null, 2));
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=D76DF713FC3000FE64756E2164756E21
830
+ //# debugId=D6F1EBFA208B3E4B64756E2164756E21