scavio 0.24.1 → 0.26.0

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
@@ -1,13 +1,14 @@
1
1
  # Scavio
2
2
 
3
3
  TypeScript SDK for the [Scavio API](https://scavio.dev?utm_source=npm-scavio-js&utm_medium=package&utm_campaign=readme) — real-time structured web
4
- data across 36 platforms on one API key, plus `extract()` to read
4
+ data across 38 platforms on one API key, plus `extract()` to read
5
5
  any URL as clean Markdown, and `extract.map()` / `extract.crawl()` /
6
6
  `extract.batch()` to map, crawl and batch-extract whole websites.
7
7
 
8
8
  Structured JSON in, structured JSON out. No per-site parsers to maintain.
9
9
 
10
10
  - **Search and SERP** — Google (organic, news, maps, shopping, flights, hotels, trends, AI Mode)
11
+ - **AI assistants** — ChatGPT and Gemini answers with the sources they cite and the products they recommend
11
12
  - **E-commerce** — Amazon, Walmart, Costco, Mercado Libre, eBay, Target, Home Depot, TikTok Shop
12
13
  - **Real estate and travel** — Zillow, Redfin, Realtor.com, Rightmove, Booking, Airbnb, Tripadvisor
13
14
  - **Reviews and local** — Trustpilot, Yelp, G2, Capterra, Glassdoor, App Store, Google Play
@@ -261,6 +262,63 @@ await client.google.news({ query: "openai" });
261
262
  await client.google.trends({ query: "bitcoin" });
262
263
  ```
263
264
 
265
+ #### Migrating from the Google Custom Search JSON API (new in 0.25.0)
266
+
267
+ `google.customSearch` takes the Custom Search JSON API (`cse.list`) parameters and
268
+ returns the same `customsearch#search` response: `items[]` with `title`, `link`,
269
+ `snippet` and `displayLink`, `searchInformation.totalResults` and
270
+ `queries.nextPage`, so code that parsed Custom Search results keeps working.
271
+ Options are snake_case like the rest of this SDK and are sent as the CSE wire
272
+ names (`site_search` -> `siteSearch`, `date_restrict` -> `dateRestrict`). 1 credit.
273
+
274
+ ```typescript
275
+ const res = await client.google.customSearch({
276
+ q: "abortcontroller fetch timeout",
277
+ num: 5,
278
+ site_search: "stackoverflow.com", // enforced on the returned results
279
+ date_restrict: "y1",
280
+ });
281
+ for (const item of res.items ?? []) console.log(item.displayLink, item.title, item.link);
282
+ const next = res.queries.nextPage?.[0]?.startIndex;
283
+ ```
284
+
285
+ Not using this SDK? Keep your existing Custom Search code and change the host:
286
+ `https://api.scavio.dev/customsearch/v1?key=YOUR_SCAVIO_KEY&q=...`. `cx` is
287
+ accepted and ignored. Parameters that cannot be honoured (image search, `sort`,
288
+ `rights`) throw `BadRequestError` instead of being silently dropped. For the full
289
+ SERP (knowledge graph, AI overview, People Also Ask) use `google.search`.
290
+ [Docs](https://scavio.dev/docs/google-custom-search-api?utm_source=npm-scavio-js&utm_medium=package&utm_campaign=readme)
291
+
292
+ ### ChatGPT and Gemini (new in 0.26.0)
293
+
294
+ Send the prompt a buyer would ask and get the answer the assistant gives: the
295
+ full Markdown answer, the pages it cites, the web searches it ran (ChatGPT) and
296
+ the products it recommended. Both return the same shape under `data`, so one
297
+ parser tracks which brands each assistant recommends. 5 credits per answered
298
+ prompt; a failed prompt is not charged. Answers take 10-40 seconds, so both
299
+ methods raise the request timeout to 120s when the client's is shorter.
300
+
301
+ ```typescript
302
+ const prompt = "What are the best CRM tools for small agencies?";
303
+
304
+ const chatgpt = await client.chatgpt.prompt({ prompt, country: "us" });
305
+ const gemini = await client.gemini.prompt({ prompt });
306
+
307
+ for (const { data } of [chatgpt, gemini] as any[]) {
308
+ console.log(data.platform, "mentions HubSpot:", data.answer.markdown.includes("HubSpot"));
309
+ console.log(" cited:", data.sources.slice(0, 5).map((s: any) => s.url));
310
+ console.log(" products:", data.shopping.map((p: any) => p.title));
311
+ }
312
+
313
+ // ChatGPT also returns each source's title and publisher and the searches it ran.
314
+ console.log((chatgpt as any).data.search_queries);
315
+ ```
316
+
317
+ Options: `chatgpt.prompt({ prompt, model?, country?, include_html? })` (prompt up
318
+ to 1024 characters) and `gemini.prompt({ prompt })` (up to 4000).
319
+ [ChatGPT docs](https://scavio.dev/docs/chatgpt-api?utm_source=npm-scavio-js&utm_medium=package&utm_campaign=readme) |
320
+ [Gemini docs](https://scavio.dev/docs/gemini-api?utm_source=npm-scavio-js&utm_medium=package&utm_campaign=readme)
321
+
264
322
  ### Amazon
265
323
 
266
324
  Responses are normalized to a stable shape (see the breaking-change note
package/dist/index.cjs CHANGED
@@ -30,18 +30,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AI_PROMPT_TIMEOUT: () => AI_PROMPT_TIMEOUT,
33
34
  AirbnbNamespace: () => AirbnbNamespace,
34
35
  AmazonNamespace: () => AmazonNamespace,
35
36
  AppStoreNamespace: () => AppStoreNamespace,
36
37
  BadRequestError: () => BadRequestError,
37
38
  BookingNamespace: () => BookingNamespace,
38
39
  CapterraNamespace: () => CapterraNamespace,
40
+ ChatgptNamespace: () => ChatgptNamespace,
39
41
  CompaniesHouseNamespace: () => CompaniesHouseNamespace,
40
42
  CostcoNamespace: () => CostcoNamespace,
41
43
  DEFAULT_MAX_REQUESTS_PER_SECOND: () => DEFAULT_MAX_REQUESTS_PER_SECOND,
42
44
  EbayNamespace: () => EbayNamespace,
43
45
  ExtractNamespace: () => ExtractNamespace,
44
46
  G2Namespace: () => G2Namespace,
47
+ GeminiNamespace: () => GeminiNamespace,
45
48
  GlassdoorNamespace: () => GlassdoorNamespace,
46
49
  GoogleAdsNamespace: () => GoogleAdsNamespace,
47
50
  GoogleNamespace: () => GoogleNamespace,
@@ -232,7 +235,7 @@ function parseRetryAfter(header) {
232
235
  var BASE_URL = "https://api.scavio.dev";
233
236
  var DEFAULT_TIMEOUT = 3e4;
234
237
  var DEFAULT_MAX_RETRIES = 2;
235
- var SDK_VERSION = true ? "0.24.1" : "0.0.0";
238
+ var SDK_VERSION = true ? "0.26.0" : "0.0.0";
236
239
  var USER_AGENT = `scavio-js/${SDK_VERSION}`;
237
240
  function isServerRuntime() {
238
241
  const g = globalThis;
@@ -421,6 +424,15 @@ var AmazonNamespace = class {
421
424
  };
422
425
 
423
426
  // src/namespaces/google.ts
427
+ var CUSTOM_SEARCH_WIRE = {
428
+ date_restrict: "dateRestrict",
429
+ site_search: "siteSearch",
430
+ site_search_filter: "siteSearchFilter",
431
+ exact_terms: "exactTerms",
432
+ exclude_terms: "excludeTerms",
433
+ or_terms: "orTerms",
434
+ file_type: "fileType"
435
+ };
424
436
  var GoogleNamespace = class {
425
437
  constructor(client) {
426
438
  this.client = client;
@@ -430,6 +442,21 @@ var GoogleNamespace = class {
430
442
  async search(options) {
431
443
  return this.client._post("/api/v2/google", options);
432
444
  }
445
+ /**
446
+ * Google search in the Custom Search JSON API format: a drop-in for cse.list.
447
+ * Returns customsearch#search (items[], searchInformation, queries.nextPage)
448
+ * plus a scavio billing object, so CSE parsing code keeps working. For the
449
+ * full SERP (knowledge graph, AI overview, People Also Ask) use search().
450
+ * Unsupported CSE params (image search, sort, rights) throw BadRequestError.
451
+ * 1 credit.
452
+ */
453
+ async customSearch(options) {
454
+ const body = {};
455
+ for (const [key, value] of Object.entries(options)) {
456
+ body[CUSTOM_SEARCH_WIRE[key] ?? key] = value;
457
+ }
458
+ return await this.client._post("/api/v1/google/customsearch", body);
459
+ }
433
460
  /** Google AI Mode answer. */
434
461
  async aiMode(options) {
435
462
  return this.client._post("/api/v2/google/ai-mode", options);
@@ -2792,6 +2819,43 @@ var TrustpilotNamespace = class {
2792
2819
  }
2793
2820
  };
2794
2821
 
2822
+ // src/namespaces/chatgpt.ts
2823
+ var AI_PROMPT_TIMEOUT = 12e4;
2824
+ var ChatgptNamespace = class {
2825
+ constructor(client) {
2826
+ this.client = client;
2827
+ }
2828
+ client;
2829
+ /**
2830
+ * Send a prompt to ChatGPT and get the answer it gives: the full Markdown
2831
+ * answer, every page it cites (title, publisher, date), the web searches it
2832
+ * ran and the products it recommended. Built for AI visibility monitoring.
2833
+ *
2834
+ * Costs 5 credits per answered prompt; failed prompts are not charged.
2835
+ */
2836
+ async prompt(options) {
2837
+ return this.client._post("/api/v1/chatgpt/prompt", options, void 0, AI_PROMPT_TIMEOUT);
2838
+ }
2839
+ };
2840
+
2841
+ // src/namespaces/gemini.ts
2842
+ var GeminiNamespace = class {
2843
+ constructor(client) {
2844
+ this.client = client;
2845
+ }
2846
+ client;
2847
+ /**
2848
+ * Send a prompt to Google Gemini and get the answer it gives as Markdown,
2849
+ * with the URLs it cites and the products it recommended. Same response
2850
+ * shape as chatgpt.prompt().
2851
+ *
2852
+ * Costs 5 credits per answered prompt; failed prompts are not charged.
2853
+ */
2854
+ async prompt(options) {
2855
+ return this.client._post("/api/v1/gemini/prompt", options, void 0, AI_PROMPT_TIMEOUT);
2856
+ }
2857
+ };
2858
+
2795
2859
  // src/namespaces/realtor.ts
2796
2860
  var RealtorNamespace = class {
2797
2861
  constructor(client) {
@@ -3194,6 +3258,8 @@ var Scavio = class extends ScavioCore {
3194
3258
  metaAds;
3195
3259
  costco;
3196
3260
  trustpilot;
3261
+ chatgpt;
3262
+ gemini;
3197
3263
  realtor;
3198
3264
  rightmove;
3199
3265
  mercadolibre;
@@ -3251,6 +3317,8 @@ var Scavio = class extends ScavioCore {
3251
3317
  this.metaAds = new MetaAdsNamespace(this);
3252
3318
  this.costco = new CostcoNamespace(this);
3253
3319
  this.trustpilot = new TrustpilotNamespace(this);
3320
+ this.chatgpt = new ChatgptNamespace(this);
3321
+ this.gemini = new GeminiNamespace(this);
3254
3322
  this.realtor = new RealtorNamespace(this);
3255
3323
  this.rightmove = new RightmoveNamespace(this);
3256
3324
  this.mercadolibre = new MercadoLibreNamespace(this);
@@ -3266,13 +3334,13 @@ var Scavio = class extends ScavioCore {
3266
3334
  });
3267
3335
  }
3268
3336
  /** @internal */
3269
- async _post(path, body, headers) {
3337
+ async _post(path, body, headers, minTimeout) {
3270
3338
  return request({
3271
3339
  method: "POST",
3272
3340
  path,
3273
3341
  apiKey: this.apiKey,
3274
3342
  baseUrl: this.baseUrl,
3275
- timeout: this.timeout,
3343
+ timeout: Math.max(this.timeout, minTimeout ?? 0),
3276
3344
  maxRetries: this.maxRetries,
3277
3345
  rateLimiter: this.rateLimiter,
3278
3346
  body,
@@ -3357,18 +3425,21 @@ async function getSubtle() {
3357
3425
  }
3358
3426
  // Annotate the CommonJS export names for ESM import in node:
3359
3427
  0 && (module.exports = {
3428
+ AI_PROMPT_TIMEOUT,
3360
3429
  AirbnbNamespace,
3361
3430
  AmazonNamespace,
3362
3431
  AppStoreNamespace,
3363
3432
  BadRequestError,
3364
3433
  BookingNamespace,
3365
3434
  CapterraNamespace,
3435
+ ChatgptNamespace,
3366
3436
  CompaniesHouseNamespace,
3367
3437
  CostcoNamespace,
3368
3438
  DEFAULT_MAX_REQUESTS_PER_SECOND,
3369
3439
  EbayNamespace,
3370
3440
  ExtractNamespace,
3371
3441
  G2Namespace,
3442
+ GeminiNamespace,
3372
3443
  GlassdoorNamespace,
3373
3444
  GoogleAdsNamespace,
3374
3445
  GoogleNamespace,