@mendable/firecrawl-js 4.47.0 → 4.49.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.
@@ -12,7 +12,6 @@ import type {
12
12
  import { SdkError } from "../types";
13
13
  import { HttpClient } from "../utils/httpClient";
14
14
  import { throwForBadResponse } from "../utils/errorHandler";
15
- import { getVersion } from "../utils/getVersion";
16
15
 
17
16
  const BASE = "/v2/search/research";
18
17
 
@@ -32,10 +31,14 @@ function appendParam(
32
31
  }
33
32
  }
34
33
 
35
- function withQuery(path: string, params: URLSearchParams): string {
34
+ function withQuery(
35
+ origin: string,
36
+ path: string,
37
+ params: URLSearchParams,
38
+ ): string {
36
39
  // Research endpoints are GETs, so the POST-body origin injection in
37
40
  // HttpClient never applies — attach it as a query param instead.
38
- params.append("origin", `js-sdk@${getVersion()}`);
41
+ params.append("origin", origin);
39
42
  const qs = params.toString();
40
43
  return qs ? `${path}?${qs}` : path;
41
44
  }
@@ -121,7 +124,7 @@ export class ResearchClient {
121
124
  appendParam(params, "to", options.to);
122
125
  try {
123
126
  const res = await this.http.get<SearchPapersResponse>(
124
- withQuery(`${BASE}/papers`, params),
127
+ withQuery(this.http.getOrigin(), `${BASE}/papers`, params),
125
128
  );
126
129
  if (res.status !== 200) throwForBadResponse(res, "search papers");
127
130
  return res.data;
@@ -161,7 +164,13 @@ export class ResearchClient {
161
164
  try {
162
165
  const res = await this.http.get<
163
166
  PaperMetadataResponse | ReadPaperResponse
164
- >(withQuery(`${BASE}/papers/${encodeURIComponent(id)}`, params));
167
+ >(
168
+ withQuery(
169
+ this.http.getOrigin(),
170
+ `${BASE}/papers/${encodeURIComponent(id)}`,
171
+ params,
172
+ ),
173
+ );
165
174
  if (res.status !== 200) throwForBadResponse(res, "get paper");
166
175
  return res.data;
167
176
  } catch (err) {
@@ -191,7 +200,11 @@ export class ResearchClient {
191
200
  appendParam(params, "anchor", options.anchor);
192
201
  try {
193
202
  const res = await this.http.get<SimilarPapersResponse>(
194
- withQuery(`${BASE}/papers/${encodeURIComponent(id)}/similar`, params),
203
+ withQuery(
204
+ this.http.getOrigin(),
205
+ `${BASE}/papers/${encodeURIComponent(id)}/similar`,
206
+ params,
207
+ ),
195
208
  );
196
209
  if (res.status !== 200) throwForBadResponse(res, "find similar papers");
197
210
  return res.data;
@@ -226,7 +239,7 @@ export class ResearchClient {
226
239
  appendParam(params, "k", options.k);
227
240
  try {
228
241
  const res = await this.http.get<GitHubSearchResponse>(
229
- withQuery(`${BASE}/github`, params),
242
+ withQuery(this.http.getOrigin(), `${BASE}/github`, params),
230
243
  );
231
244
  if (res.status !== 200) throwForBadResponse(res, "search github");
232
245
  return res.data;
@@ -12,6 +12,7 @@ export interface HttpClientOptions {
12
12
  timeoutMs?: number;
13
13
  maxRetries?: number;
14
14
  backoffFactor?: number; // seconds factor for 0.5, 1, 2...
15
+ origin?: string;
15
16
  }
16
17
 
17
18
  export interface RequestOptions {
@@ -25,12 +26,14 @@ export class HttpClient {
25
26
  private readonly apiUrl: string;
26
27
  private readonly maxRetries: number;
27
28
  private readonly backoffFactor: number;
29
+ private readonly origin: string;
28
30
 
29
31
  constructor(options: HttpClientOptions) {
30
32
  this.apiKey = options.apiKey;
31
33
  this.apiUrl = options.apiUrl.replace(/\/$/, "");
32
34
  this.maxRetries = options.maxRetries ?? 3;
33
35
  this.backoffFactor = options.backoffFactor ?? 0.5;
36
+ this.origin = options.origin || `js-sdk@${getVersion()}`;
34
37
  this.instance = axios.create({
35
38
  baseURL: this.apiUrl,
36
39
  timeout: options.timeoutMs ?? 300000,
@@ -52,6 +55,11 @@ export class HttpClient {
52
55
  return this.apiKey;
53
56
  }
54
57
 
58
+ /** The attribution origin stamped into requests that do not set their own. */
59
+ getOrigin(): string {
60
+ return this.origin;
61
+ }
62
+
55
63
  /** The client-wide default request timeout, for callers that need to
56
64
  * extend a specific request beyond it (e.g. scrape auto-resume). */
57
65
  getTimeoutMs(): number {
@@ -61,7 +69,6 @@ export class HttpClient {
61
69
  private async request<T = any>(
62
70
  config: AxiosRequestConfig,
63
71
  ): Promise<AxiosResponse<T>> {
64
- const version = getVersion();
65
72
  config.headers = {
66
73
  ...(config.headers || {}),
67
74
  };
@@ -89,9 +96,9 @@ export class HttpClient {
89
96
  cfg.data = {
90
97
  ...data,
91
98
  origin:
92
- typeof data.origin === "string" && data.origin.includes("mcp")
99
+ typeof data.origin === "string" && data.origin
93
100
  ? data.origin
94
- : `js-sdk@${version}`,
101
+ : this.origin,
95
102
  };
96
103
  }
97
104
 
@@ -0,0 +1,38 @@
1
+ let warned = false;
2
+
3
+ /** Emits the deprecation warning for v1-style method calls, once per process. */
4
+ export function warnV1Usage(): void {
5
+ if (warned) return;
6
+ warned = true;
7
+ const message =
8
+ "firecrawl: v1-style methods (scrapeUrl, crawlUrl, batchScrapeUrls, ...) are deprecated and mapped to the v2 API. " +
9
+ "Use scrape(), crawl(), batchScrape() and the other v2 methods instead.";
10
+ if (typeof process !== "undefined" && typeof process.emitWarning === "function") {
11
+ process.emitWarning(message, { type: "DeprecationWarning", code: "FIRECRAWL_V1_METHOD" });
12
+ } else {
13
+ console.warn(message);
14
+ }
15
+ }
16
+
17
+ /** v1 crawl options that have a v2 equivalent. */
18
+ export type V1CrawlOptions = { maxDepth?: number; allowBackwardLinks?: boolean; ignoreSitemap?: boolean };
19
+
20
+ /** Renames v1 crawl options to their v2 names; v2 options given alongside win. */
21
+ export function toV2CrawlOptions<T extends object>(req: T & V1CrawlOptions): T {
22
+ const { maxDepth, allowBackwardLinks, ignoreSitemap, ...rest } = req;
23
+ return {
24
+ ...(maxDepth != null && { maxDiscoveryDepth: maxDepth }),
25
+ ...(allowBackwardLinks != null && { crawlEntireDomain: allowBackwardLinks }),
26
+ ...(ignoreSitemap != null && { sitemap: ignoreSitemap ? "skip" : "include" }),
27
+ ...rest,
28
+ } as T;
29
+ }
30
+
31
+ /** A v2 result with the `success` flag v1 results carried. */
32
+ export type V1Result<T> = T & { success: true };
33
+
34
+ /** Warns once, then runs the v2 call and adds the v1 `success` flag to its result. */
35
+ export async function callV1<T extends object>(call: () => Promise<T>): Promise<V1Result<T>> {
36
+ warnV1Usage();
37
+ return { ...(await call()), success: true };
38
+ }