@mendable/firecrawl-js 4.19.0 → 4.20.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/audit-ci.jsonc +5 -2
- package/dist/{chunk-JJY4NJXL.js → chunk-OVLAEYRZ.js} +1 -1
- package/dist/index.cjs +166 -70
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +167 -71
- package/dist/{package-HMEPZJ3J.js → package-4Q7WA3UI.js} +1 -1
- package/package.json +1 -1
- package/src/__tests__/unit/v2/scrape-browser.unit.test.ts +39 -12
- package/src/v2/methods/batch.ts +89 -28
- package/src/v2/methods/browser.ts +19 -11
- package/src/v2/methods/map.ts +36 -9
- package/src/v2/methods/parse.ts +15 -9
- package/src/v2/methods/scrape.ts +32 -13
- package/src/v2/methods/search.ts +38 -10
- package/src/v2/utils/httpClient.ts +36 -16
- package/src/v2/watcher.ts +44 -24
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import axios, {
|
|
1
|
+
import axios, {
|
|
2
|
+
type AxiosInstance,
|
|
3
|
+
type AxiosRequestConfig,
|
|
4
|
+
type AxiosResponse,
|
|
5
|
+
} from "axios";
|
|
2
6
|
import { getVersion } from "./getVersion";
|
|
3
7
|
|
|
4
8
|
export interface HttpClientOptions {
|
|
@@ -9,6 +13,11 @@ export interface HttpClientOptions {
|
|
|
9
13
|
backoffFactor?: number; // seconds factor for 0.5, 1, 2...
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
export interface RequestOptions {
|
|
17
|
+
headers?: Record<string, string>;
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
12
21
|
export class HttpClient {
|
|
13
22
|
private instance: AxiosInstance;
|
|
14
23
|
private readonly apiKey: string;
|
|
@@ -39,7 +48,9 @@ export class HttpClient {
|
|
|
39
48
|
return this.apiKey;
|
|
40
49
|
}
|
|
41
50
|
|
|
42
|
-
private async request<T = any>(
|
|
51
|
+
private async request<T = any>(
|
|
52
|
+
config: AxiosRequestConfig,
|
|
53
|
+
): Promise<AxiosResponse<T>> {
|
|
43
54
|
const version = getVersion();
|
|
44
55
|
config.headers = {
|
|
45
56
|
...(config.headers || {}),
|
|
@@ -64,12 +75,13 @@ export class HttpClient {
|
|
|
64
75
|
["post", "put", "patch"].includes(cfg.method.toLowerCase())
|
|
65
76
|
) {
|
|
66
77
|
const data = (cfg.data ?? {}) as Record<string, unknown>;
|
|
67
|
-
cfg.data = {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
cfg.data = {
|
|
79
|
+
...data,
|
|
80
|
+
origin:
|
|
81
|
+
typeof data.origin === "string" && data.origin.includes("mcp")
|
|
82
|
+
? data.origin
|
|
83
|
+
: `js-sdk@${version}`,
|
|
84
|
+
};
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
if (isFormDataBody) {
|
|
@@ -98,25 +110,34 @@ export class HttpClient {
|
|
|
98
110
|
}
|
|
99
111
|
|
|
100
112
|
private sleep(seconds: number): Promise<void> {
|
|
101
|
-
return new Promise(
|
|
113
|
+
return new Promise(r => setTimeout(r, seconds * 1000));
|
|
102
114
|
}
|
|
103
115
|
|
|
104
|
-
post<T = any>(
|
|
105
|
-
|
|
116
|
+
post<T = any>(
|
|
117
|
+
endpoint: string,
|
|
118
|
+
body: Record<string, unknown>,
|
|
119
|
+
options?: RequestOptions,
|
|
120
|
+
) {
|
|
121
|
+
return this.request<T>({
|
|
122
|
+
method: "post",
|
|
123
|
+
url: endpoint,
|
|
124
|
+
data: body,
|
|
125
|
+
headers: options?.headers,
|
|
126
|
+
timeout: options?.timeoutMs,
|
|
127
|
+
});
|
|
106
128
|
}
|
|
107
129
|
|
|
108
130
|
postMultipart<T = any>(
|
|
109
131
|
endpoint: string,
|
|
110
132
|
formData: FormData,
|
|
111
|
-
|
|
112
|
-
timeoutMs?: number,
|
|
133
|
+
options?: RequestOptions,
|
|
113
134
|
) {
|
|
114
135
|
return this.request<T>({
|
|
115
136
|
method: "post",
|
|
116
137
|
url: endpoint,
|
|
117
138
|
data: formData,
|
|
118
|
-
headers,
|
|
119
|
-
timeout: timeoutMs,
|
|
139
|
+
headers: options?.headers,
|
|
140
|
+
timeout: options?.timeoutMs,
|
|
120
141
|
});
|
|
121
142
|
}
|
|
122
143
|
|
|
@@ -134,4 +155,3 @@ export class HttpClient {
|
|
|
134
155
|
return headers;
|
|
135
156
|
}
|
|
136
157
|
}
|
|
137
|
-
|
package/src/v2/watcher.ts
CHANGED
|
@@ -109,24 +109,37 @@ export class Watcher extends EventEmitter {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
async start(): Promise<void> {
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
this.
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
this.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
112
|
+
return new Promise<void>((resolve, reject) => {
|
|
113
|
+
const onDone = () => { cleanup(); resolve(); };
|
|
114
|
+
const onError = (err: any) => { cleanup(); resolve(); };
|
|
115
|
+
const cleanup = () => {
|
|
116
|
+
this.removeListener("done", onDone);
|
|
117
|
+
this.removeListener("error", onError);
|
|
118
|
+
};
|
|
119
|
+
this.on("done", onDone);
|
|
120
|
+
this.on("error", onError);
|
|
121
|
+
|
|
122
|
+
(async () => {
|
|
123
|
+
try {
|
|
124
|
+
const url = this.buildWsUrl();
|
|
125
|
+
const wsCtor = await getWebSocketCtor();
|
|
126
|
+
if (!wsCtor) {
|
|
127
|
+
this.pollLoop();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
this.ws = new wsCtor(url, this.http.getApiKey()) as any;
|
|
131
|
+
if (this.ws && "binaryType" in this.ws) {
|
|
132
|
+
(this.ws as any).binaryType = "arraybuffer";
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (this.ws) {
|
|
136
|
+
this.attachWsHandlers(this.ws);
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
this.pollLoop();
|
|
140
|
+
}
|
|
141
|
+
})();
|
|
142
|
+
});
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
private attachWsHandlers(ws: WebSocket) {
|
|
@@ -150,14 +163,14 @@ export class Watcher extends EventEmitter {
|
|
|
150
163
|
}
|
|
151
164
|
if (type === "document") {
|
|
152
165
|
const doc = body.data;
|
|
153
|
-
if (doc) this.
|
|
166
|
+
if (doc) this.emitDocuments([doc]);
|
|
154
167
|
return;
|
|
155
168
|
}
|
|
156
169
|
if (type === "done") {
|
|
157
170
|
const payload = body.data || body;
|
|
158
171
|
const data = (payload.data || []) as Document[];
|
|
159
172
|
if (data.length) this.emitDocuments(data);
|
|
160
|
-
this.emit("done", { status: "completed", data, id: this.jobId });
|
|
173
|
+
this.emit("done", { status: "completed", data, id: this.jobId, total: payload.total, completed: payload.completed, creditsUsed: payload.creditsUsed });
|
|
161
174
|
this.close();
|
|
162
175
|
return;
|
|
163
176
|
}
|
|
@@ -166,7 +179,10 @@ export class Watcher extends EventEmitter {
|
|
|
166
179
|
} catch {
|
|
167
180
|
// ignore
|
|
168
181
|
}
|
|
169
|
-
if (timeoutMs && Date.now() - startTs > timeoutMs)
|
|
182
|
+
if (timeoutMs && Date.now() - startTs > timeoutMs) {
|
|
183
|
+
this.emit("error", { status: "failed", data: [], error: "Watcher timeout", id: this.jobId });
|
|
184
|
+
this.close();
|
|
185
|
+
}
|
|
170
186
|
};
|
|
171
187
|
ws.onerror = () => {
|
|
172
188
|
this.emit("error", { status: "failed", data: [], error: "WebSocket error", id: this.jobId });
|
|
@@ -227,7 +243,7 @@ export class Watcher extends EventEmitter {
|
|
|
227
243
|
};
|
|
228
244
|
this.emit("snapshot", snap);
|
|
229
245
|
if (["completed", "failed", "cancelled"].includes(status)) {
|
|
230
|
-
this.emit("done", { status, data, id: this.jobId });
|
|
246
|
+
this.emit("done", { status, data, id: this.jobId, total: payload.total ?? 0, completed: payload.completed ?? 0, creditsUsed: payload.creditsUsed });
|
|
231
247
|
this.close();
|
|
232
248
|
}
|
|
233
249
|
}
|
|
@@ -243,14 +259,18 @@ export class Watcher extends EventEmitter {
|
|
|
243
259
|
this.emitDocuments((snap.data || []) as Document[]);
|
|
244
260
|
this.emit("snapshot", snap);
|
|
245
261
|
if (["completed", "failed", "cancelled"].includes(snap.status)) {
|
|
246
|
-
this.emit("done", { status: snap.status, data: snap.data, id: this.jobId });
|
|
262
|
+
this.emit("done", { status: snap.status, data: snap.data, id: this.jobId, total: (snap as any).total ?? 0, completed: (snap as any).completed ?? 0, creditsUsed: (snap as any).creditsUsed });
|
|
247
263
|
this.close();
|
|
248
264
|
break;
|
|
249
265
|
}
|
|
250
266
|
} catch {
|
|
251
267
|
// ignore polling errors
|
|
252
268
|
}
|
|
253
|
-
if (timeoutMs && Date.now() - startTs > timeoutMs)
|
|
269
|
+
if (timeoutMs && Date.now() - startTs > timeoutMs) {
|
|
270
|
+
this.emit("error", { status: "failed", data: [], error: "Watcher timeout", id: this.jobId });
|
|
271
|
+
this.close();
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
254
274
|
await new Promise((r) => setTimeout(r, Math.max(1000, this.pollInterval * 1000)));
|
|
255
275
|
}
|
|
256
276
|
}
|