firecrawl 4.21.1 → 4.22.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/{chunk-EH7NHUN5.js → chunk-WTZQ5IMF.js} +3 -3
- package/dist/index.cjs +232 -5
- package/dist/index.d.cts +166 -3
- package/dist/index.d.ts +166 -3
- package/dist/index.js +231 -4
- package/dist/{package-7423KYJY.js → package-YDTOLYXI.js} +1 -1
- package/package.json +2 -2
- package/src/__tests__/unit/v2/pagination.test.ts +21 -0
- package/src/__tests__/unit/v2/validation.test.ts +21 -0
- package/src/v2/client.ts +85 -0
- package/src/v2/methods/monitor.ts +181 -0
- package/src/v2/types.ts +164 -0
- package/src/v2/utils/httpClient.ts +14 -0
- package/src/v2/utils/pagination.ts +12 -9
- package/src/v2/utils/validation.ts +52 -0
package/src/v2/client.ts
CHANGED
|
@@ -32,6 +32,16 @@ import {
|
|
|
32
32
|
listBrowsers,
|
|
33
33
|
} from "./methods/browser";
|
|
34
34
|
import { getConcurrency, getCreditUsage, getQueueStatus, getTokenUsage, getCreditUsageHistorical, getTokenUsageHistorical } from "./methods/usage";
|
|
35
|
+
import {
|
|
36
|
+
createMonitor as createMonitorMethod,
|
|
37
|
+
deleteMonitor as deleteMonitorMethod,
|
|
38
|
+
getMonitor as getMonitorMethod,
|
|
39
|
+
getMonitorCheck as getMonitorCheckMethod,
|
|
40
|
+
listMonitorChecks as listMonitorChecksMethod,
|
|
41
|
+
listMonitors as listMonitorsMethod,
|
|
42
|
+
runMonitor as runMonitorMethod,
|
|
43
|
+
updateMonitor as updateMonitorMethod,
|
|
44
|
+
} from "./methods/monitor";
|
|
35
45
|
import type {
|
|
36
46
|
Document,
|
|
37
47
|
ParseFile,
|
|
@@ -60,6 +70,14 @@ import type {
|
|
|
60
70
|
ScrapeExecuteRequest,
|
|
61
71
|
ScrapeExecuteResponse,
|
|
62
72
|
ScrapeBrowserDeleteResponse,
|
|
73
|
+
CreateMonitorRequest,
|
|
74
|
+
ListMonitorChecksOptions,
|
|
75
|
+
ListMonitorsOptions,
|
|
76
|
+
Monitor,
|
|
77
|
+
MonitorCheck,
|
|
78
|
+
MonitorCheckDetail,
|
|
79
|
+
GetMonitorCheckOptions,
|
|
80
|
+
UpdateMonitorRequest,
|
|
63
81
|
} from "./types";
|
|
64
82
|
import { Watcher } from "./watcher";
|
|
65
83
|
import type { WatcherOptions } from "./watcher";
|
|
@@ -276,6 +294,73 @@ export class FirecrawlClient {
|
|
|
276
294
|
return crawlParamsPreview(this.http, url, prompt);
|
|
277
295
|
}
|
|
278
296
|
|
|
297
|
+
// Monitor
|
|
298
|
+
/**
|
|
299
|
+
* Create a scheduled monitor.
|
|
300
|
+
*/
|
|
301
|
+
async createMonitor(request: CreateMonitorRequest): Promise<Monitor> {
|
|
302
|
+
return createMonitorMethod(this.http, request);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* List monitors for the authenticated team.
|
|
307
|
+
*/
|
|
308
|
+
async listMonitors(options?: ListMonitorsOptions): Promise<Monitor[]> {
|
|
309
|
+
return listMonitorsMethod(this.http, options);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Get a monitor by id.
|
|
314
|
+
*/
|
|
315
|
+
async getMonitor(monitorId: string): Promise<Monitor> {
|
|
316
|
+
return getMonitorMethod(this.http, monitorId);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Update a monitor.
|
|
321
|
+
*/
|
|
322
|
+
async updateMonitor(
|
|
323
|
+
monitorId: string,
|
|
324
|
+
request: UpdateMonitorRequest,
|
|
325
|
+
): Promise<Monitor> {
|
|
326
|
+
return updateMonitorMethod(this.http, monitorId, request);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Delete a monitor.
|
|
331
|
+
*/
|
|
332
|
+
async deleteMonitor(monitorId: string): Promise<boolean> {
|
|
333
|
+
return deleteMonitorMethod(this.http, monitorId);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Trigger a manual monitor check.
|
|
338
|
+
*/
|
|
339
|
+
async runMonitor(monitorId: string): Promise<MonitorCheck> {
|
|
340
|
+
return runMonitorMethod(this.http, monitorId);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* List checks for a monitor.
|
|
345
|
+
*/
|
|
346
|
+
async listMonitorChecks(
|
|
347
|
+
monitorId: string,
|
|
348
|
+
options?: ListMonitorChecksOptions,
|
|
349
|
+
): Promise<MonitorCheck[]> {
|
|
350
|
+
return listMonitorChecksMethod(this.http, monitorId, options);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Get a monitor check with paginated page results and inline diffs.
|
|
355
|
+
*/
|
|
356
|
+
async getMonitorCheck(
|
|
357
|
+
monitorId: string,
|
|
358
|
+
checkId: string,
|
|
359
|
+
options?: GetMonitorCheckOptions,
|
|
360
|
+
): Promise<MonitorCheckDetail> {
|
|
361
|
+
return getMonitorCheckMethod(this.http, monitorId, checkId, options);
|
|
362
|
+
}
|
|
363
|
+
|
|
279
364
|
// Batch
|
|
280
365
|
/**
|
|
281
366
|
* Start a batch scrape job for multiple URLs (async).
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CreateMonitorRequest,
|
|
3
|
+
type ListMonitorsOptions,
|
|
4
|
+
type ListMonitorChecksOptions,
|
|
5
|
+
type Monitor,
|
|
6
|
+
type MonitorCheck,
|
|
7
|
+
type MonitorCheckDetail,
|
|
8
|
+
type MonitorCheckPage,
|
|
9
|
+
type GetMonitorCheckOptions,
|
|
10
|
+
type UpdateMonitorRequest,
|
|
11
|
+
} from "../types";
|
|
12
|
+
import { HttpClient } from "../utils/httpClient";
|
|
13
|
+
import {
|
|
14
|
+
throwForBadResponse,
|
|
15
|
+
normalizeAxiosError,
|
|
16
|
+
} from "../utils/errorHandler";
|
|
17
|
+
import { fetchAllPages } from "../utils/pagination";
|
|
18
|
+
|
|
19
|
+
type ApiResponse<T> = {
|
|
20
|
+
success: boolean;
|
|
21
|
+
data?: T;
|
|
22
|
+
id?: string;
|
|
23
|
+
error?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function queryString(params?: Record<string, unknown>): string {
|
|
27
|
+
if (!params) return "";
|
|
28
|
+
const query = new URLSearchParams();
|
|
29
|
+
for (const [key, value] of Object.entries(params)) {
|
|
30
|
+
if (value !== undefined && value !== null) query.set(key, String(value));
|
|
31
|
+
}
|
|
32
|
+
const str = query.toString();
|
|
33
|
+
return str ? `?${str}` : "";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function dataOrThrow<T>(res: { status: number; data?: ApiResponse<T> }, action: string): T {
|
|
37
|
+
if (res.status !== 200 || !res.data?.success || res.data.data == null) {
|
|
38
|
+
throwForBadResponse(res as any, action);
|
|
39
|
+
}
|
|
40
|
+
return res.data.data;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function createMonitor(
|
|
44
|
+
http: HttpClient,
|
|
45
|
+
request: CreateMonitorRequest,
|
|
46
|
+
): Promise<Monitor> {
|
|
47
|
+
try {
|
|
48
|
+
const res = await http.post<ApiResponse<Monitor>>("/v2/monitor", request as any);
|
|
49
|
+
return dataOrThrow(res, "create monitor");
|
|
50
|
+
} catch (err: any) {
|
|
51
|
+
if (err?.isAxiosError) return normalizeAxiosError(err, "create monitor");
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function listMonitors(
|
|
57
|
+
http: HttpClient,
|
|
58
|
+
options?: ListMonitorsOptions,
|
|
59
|
+
): Promise<Monitor[]> {
|
|
60
|
+
try {
|
|
61
|
+
const res = await http.get<ApiResponse<Monitor[]>>(
|
|
62
|
+
`/v2/monitor${queryString(options as Record<string, unknown>)}`,
|
|
63
|
+
);
|
|
64
|
+
return dataOrThrow(res, "list monitors");
|
|
65
|
+
} catch (err: any) {
|
|
66
|
+
if (err?.isAxiosError) return normalizeAxiosError(err, "list monitors");
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function getMonitor(
|
|
72
|
+
http: HttpClient,
|
|
73
|
+
monitorId: string,
|
|
74
|
+
): Promise<Monitor> {
|
|
75
|
+
try {
|
|
76
|
+
const res = await http.get<ApiResponse<Monitor>>(`/v2/monitor/${monitorId}`);
|
|
77
|
+
return dataOrThrow(res, "get monitor");
|
|
78
|
+
} catch (err: any) {
|
|
79
|
+
if (err?.isAxiosError) return normalizeAxiosError(err, "get monitor");
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function updateMonitor(
|
|
85
|
+
http: HttpClient,
|
|
86
|
+
monitorId: string,
|
|
87
|
+
request: UpdateMonitorRequest,
|
|
88
|
+
): Promise<Monitor> {
|
|
89
|
+
try {
|
|
90
|
+
const res = await http.patch<ApiResponse<Monitor>>(
|
|
91
|
+
`/v2/monitor/${monitorId}`,
|
|
92
|
+
request as any,
|
|
93
|
+
);
|
|
94
|
+
return dataOrThrow(res, "update monitor");
|
|
95
|
+
} catch (err: any) {
|
|
96
|
+
if (err?.isAxiosError) return normalizeAxiosError(err, "update monitor");
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function deleteMonitor(
|
|
102
|
+
http: HttpClient,
|
|
103
|
+
monitorId: string,
|
|
104
|
+
): Promise<boolean> {
|
|
105
|
+
try {
|
|
106
|
+
const res = await http.delete<ApiResponse<unknown>>(`/v2/monitor/${monitorId}`);
|
|
107
|
+
if (res.status !== 200 || !res.data?.success) {
|
|
108
|
+
throwForBadResponse(res, "delete monitor");
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
} catch (err: any) {
|
|
112
|
+
if (err?.isAxiosError) return normalizeAxiosError(err, "delete monitor");
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function runMonitor(
|
|
118
|
+
http: HttpClient,
|
|
119
|
+
monitorId: string,
|
|
120
|
+
): Promise<MonitorCheck> {
|
|
121
|
+
try {
|
|
122
|
+
const res = await http.post<ApiResponse<MonitorCheck>>(
|
|
123
|
+
`/v2/monitor/${monitorId}/run`,
|
|
124
|
+
{},
|
|
125
|
+
);
|
|
126
|
+
return dataOrThrow(res, "run monitor");
|
|
127
|
+
} catch (err: any) {
|
|
128
|
+
if (err?.isAxiosError) return normalizeAxiosError(err, "run monitor");
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function listMonitorChecks(
|
|
134
|
+
http: HttpClient,
|
|
135
|
+
monitorId: string,
|
|
136
|
+
options?: ListMonitorChecksOptions,
|
|
137
|
+
): Promise<MonitorCheck[]> {
|
|
138
|
+
try {
|
|
139
|
+
const res = await http.get<ApiResponse<MonitorCheck[]>>(
|
|
140
|
+
`/v2/monitor/${monitorId}/checks${queryString(options as Record<string, unknown>)}`,
|
|
141
|
+
);
|
|
142
|
+
return dataOrThrow(res, "list monitor checks");
|
|
143
|
+
} catch (err: any) {
|
|
144
|
+
if (err?.isAxiosError) return normalizeAxiosError(err, "list monitor checks");
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function getMonitorCheck(
|
|
150
|
+
http: HttpClient,
|
|
151
|
+
monitorId: string,
|
|
152
|
+
checkId: string,
|
|
153
|
+
options?: GetMonitorCheckOptions,
|
|
154
|
+
): Promise<MonitorCheckDetail> {
|
|
155
|
+
try {
|
|
156
|
+
const { autoPaginate: _autoPaginate, maxPages: _maxPages, maxResults: _maxResults, maxWaitTime: _maxWaitTime, ...query } = options ?? {};
|
|
157
|
+
const res = await http.get<ApiResponse<MonitorCheckDetail>>(
|
|
158
|
+
`/v2/monitor/${monitorId}/checks/${checkId}${queryString(query as Record<string, unknown>)}`,
|
|
159
|
+
);
|
|
160
|
+
const detail = dataOrThrow(res, "get monitor check");
|
|
161
|
+
const next = res.data?.next ?? detail.next ?? null;
|
|
162
|
+
const auto = options?.autoPaginate ?? true;
|
|
163
|
+
if (!auto || !next) {
|
|
164
|
+
return { ...detail, next };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
...detail,
|
|
169
|
+
pages: await fetchAllPages<MonitorCheckPage>(
|
|
170
|
+
http,
|
|
171
|
+
next,
|
|
172
|
+
detail.pages || [],
|
|
173
|
+
options,
|
|
174
|
+
),
|
|
175
|
+
next: null,
|
|
176
|
+
};
|
|
177
|
+
} catch (err: any) {
|
|
178
|
+
if (err?.isAxiosError) return normalizeAxiosError(err, "get monitor check");
|
|
179
|
+
throw err;
|
|
180
|
+
}
|
|
181
|
+
}
|
package/src/v2/types.ts
CHANGED
|
@@ -52,6 +52,17 @@ export interface AttributesFormat extends Format {
|
|
|
52
52
|
}>;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
export interface QuestionFormat {
|
|
56
|
+
type: 'question';
|
|
57
|
+
question: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface HighlightsFormat {
|
|
61
|
+
type: 'highlights';
|
|
62
|
+
query: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** @deprecated Use QuestionFormat or HighlightsFormat instead. */
|
|
55
66
|
export interface QueryFormat {
|
|
56
67
|
type: 'query';
|
|
57
68
|
prompt: string;
|
|
@@ -65,6 +76,8 @@ export type FormatOption =
|
|
|
65
76
|
| ChangeTrackingFormat
|
|
66
77
|
| ScreenshotFormat
|
|
67
78
|
| AttributesFormat
|
|
79
|
+
| QuestionFormat
|
|
80
|
+
| HighlightsFormat
|
|
68
81
|
| QueryFormat;
|
|
69
82
|
|
|
70
83
|
export type ParseFormatString = Exclude<
|
|
@@ -81,6 +94,8 @@ export type ParseFormatOption =
|
|
|
81
94
|
| ParseFormat
|
|
82
95
|
| JsonFormat
|
|
83
96
|
| AttributesFormat
|
|
97
|
+
| QuestionFormat
|
|
98
|
+
| HighlightsFormat
|
|
84
99
|
| QueryFormat;
|
|
85
100
|
|
|
86
101
|
export interface LocationConfig {
|
|
@@ -450,6 +465,7 @@ export interface Document {
|
|
|
450
465
|
}>;
|
|
451
466
|
actions?: Record<string, unknown>;
|
|
452
467
|
answer?: string;
|
|
468
|
+
highlights?: string;
|
|
453
469
|
warning?: string;
|
|
454
470
|
changeTracking?: Record<string, unknown>;
|
|
455
471
|
branding?: BrandingProfile;
|
|
@@ -606,6 +622,154 @@ export interface MapOptions {
|
|
|
606
622
|
location?: LocationConfig;
|
|
607
623
|
}
|
|
608
624
|
|
|
625
|
+
export interface MonitorSchedule {
|
|
626
|
+
cron: string;
|
|
627
|
+
timezone?: string;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
export interface MonitorEmailNotification {
|
|
631
|
+
enabled?: boolean;
|
|
632
|
+
recipients?: string[];
|
|
633
|
+
includeDiffs?: boolean;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export interface MonitorNotification {
|
|
637
|
+
email?: MonitorEmailNotification;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
export interface MonitorWebhookConfig {
|
|
641
|
+
url: string;
|
|
642
|
+
headers?: Record<string, string>;
|
|
643
|
+
metadata?: Record<string, string>;
|
|
644
|
+
events?: string[];
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
export interface MonitorScrapeTarget {
|
|
648
|
+
id?: string;
|
|
649
|
+
type: 'scrape';
|
|
650
|
+
urls: string[];
|
|
651
|
+
scrapeOptions?: ScrapeOptions;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
export interface MonitorCrawlTarget {
|
|
655
|
+
id?: string;
|
|
656
|
+
type: 'crawl';
|
|
657
|
+
url: string;
|
|
658
|
+
crawlOptions?: CrawlOptions;
|
|
659
|
+
scrapeOptions?: ScrapeOptions;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export type MonitorTarget = MonitorScrapeTarget | MonitorCrawlTarget;
|
|
663
|
+
|
|
664
|
+
export interface CreateMonitorRequest {
|
|
665
|
+
name: string;
|
|
666
|
+
schedule: MonitorSchedule;
|
|
667
|
+
webhook?: MonitorWebhookConfig;
|
|
668
|
+
notification?: MonitorNotification;
|
|
669
|
+
targets: MonitorTarget[];
|
|
670
|
+
retentionDays?: number;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
export interface UpdateMonitorRequest {
|
|
674
|
+
name?: string;
|
|
675
|
+
status?: 'active' | 'paused';
|
|
676
|
+
schedule?: MonitorSchedule;
|
|
677
|
+
webhook?: MonitorWebhookConfig | null;
|
|
678
|
+
notification?: MonitorNotification | null;
|
|
679
|
+
targets?: MonitorTarget[];
|
|
680
|
+
retentionDays?: number;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
export interface MonitorSummary {
|
|
684
|
+
totalPages: number;
|
|
685
|
+
same: number;
|
|
686
|
+
changed: number;
|
|
687
|
+
new: number;
|
|
688
|
+
removed: number;
|
|
689
|
+
error: number;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
export interface Monitor {
|
|
693
|
+
id: string;
|
|
694
|
+
name: string;
|
|
695
|
+
status: 'active' | 'paused' | 'deleted';
|
|
696
|
+
schedule: MonitorSchedule;
|
|
697
|
+
nextRunAt?: string | null;
|
|
698
|
+
lastRunAt?: string | null;
|
|
699
|
+
currentCheckId?: string | null;
|
|
700
|
+
targets: MonitorTarget[];
|
|
701
|
+
webhook?: MonitorWebhookConfig | null;
|
|
702
|
+
notification?: MonitorNotification | null;
|
|
703
|
+
retentionDays: number;
|
|
704
|
+
estimatedCreditsPerMonth?: number | null;
|
|
705
|
+
lastCheckSummary?: MonitorSummary | null;
|
|
706
|
+
createdAt: string;
|
|
707
|
+
updatedAt: string;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
export interface MonitorCheck {
|
|
711
|
+
id: string;
|
|
712
|
+
monitorId: string;
|
|
713
|
+
status:
|
|
714
|
+
| 'queued'
|
|
715
|
+
| 'running'
|
|
716
|
+
| 'completed'
|
|
717
|
+
| 'failed'
|
|
718
|
+
| 'partial'
|
|
719
|
+
| 'skipped_overlap';
|
|
720
|
+
trigger: 'scheduled' | 'manual';
|
|
721
|
+
scheduledFor?: string | null;
|
|
722
|
+
startedAt?: string | null;
|
|
723
|
+
finishedAt?: string | null;
|
|
724
|
+
estimatedCredits?: number | null;
|
|
725
|
+
reservedCredits?: number | null;
|
|
726
|
+
actualCredits?: number | null;
|
|
727
|
+
billingStatus:
|
|
728
|
+
| 'not_applicable'
|
|
729
|
+
| 'reserved'
|
|
730
|
+
| 'confirmed'
|
|
731
|
+
| 'released'
|
|
732
|
+
| 'failed';
|
|
733
|
+
summary: MonitorSummary;
|
|
734
|
+
targetResults?: unknown;
|
|
735
|
+
notificationStatus?: unknown;
|
|
736
|
+
error?: string | null;
|
|
737
|
+
createdAt: string;
|
|
738
|
+
updatedAt: string;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
export interface MonitorCheckPage {
|
|
742
|
+
id: string;
|
|
743
|
+
targetId: string;
|
|
744
|
+
url: string;
|
|
745
|
+
status: 'same' | 'new' | 'changed' | 'removed' | 'error';
|
|
746
|
+
previousScrapeId?: string | null;
|
|
747
|
+
currentScrapeId?: string | null;
|
|
748
|
+
statusCode?: number | null;
|
|
749
|
+
error?: string | null;
|
|
750
|
+
metadata?: unknown;
|
|
751
|
+
diff?: unknown;
|
|
752
|
+
createdAt: string;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export interface MonitorCheckDetail extends MonitorCheck {
|
|
756
|
+
pages: MonitorCheckPage[];
|
|
757
|
+
next?: string | null;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
export interface ListMonitorsOptions {
|
|
761
|
+
limit?: number;
|
|
762
|
+
offset?: number;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
export type ListMonitorChecksOptions = ListMonitorsOptions;
|
|
766
|
+
|
|
767
|
+
export type GetMonitorCheckOptions = PaginationConfig & {
|
|
768
|
+
limit?: number;
|
|
769
|
+
skip?: number;
|
|
770
|
+
status?: MonitorCheckPage["status"];
|
|
771
|
+
};
|
|
772
|
+
|
|
609
773
|
export interface ExtractResponse {
|
|
610
774
|
success?: boolean;
|
|
611
775
|
id?: string;
|
|
@@ -149,6 +149,20 @@ export class HttpClient {
|
|
|
149
149
|
return this.request<T>({ method: "delete", url: endpoint, headers });
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
patch<T = any>(
|
|
153
|
+
endpoint: string,
|
|
154
|
+
body: Record<string, unknown>,
|
|
155
|
+
options?: RequestOptions,
|
|
156
|
+
) {
|
|
157
|
+
return this.request<T>({
|
|
158
|
+
method: "patch",
|
|
159
|
+
url: endpoint,
|
|
160
|
+
data: body,
|
|
161
|
+
headers: options?.headers,
|
|
162
|
+
timeout: options?.timeoutMs,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
152
166
|
prepareHeaders(idempotencyKey?: string): Record<string, string> {
|
|
153
167
|
const headers: Record<string, string> = {};
|
|
154
168
|
if (idempotencyKey) headers["x-idempotency-key"] = idempotencyKey;
|
|
@@ -2,14 +2,14 @@ import type { HttpClient } from "../utils/httpClient";
|
|
|
2
2
|
import type { Document, PaginationConfig } from "../types";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Shared helper to follow `next`
|
|
5
|
+
* Shared helper to follow `next` URLs and aggregate paginated result arrays.
|
|
6
6
|
*/
|
|
7
|
-
export async function fetchAllPages(
|
|
7
|
+
export async function fetchAllPages<T = Document>(
|
|
8
8
|
http: HttpClient,
|
|
9
9
|
nextUrl: string,
|
|
10
|
-
initial:
|
|
10
|
+
initial: T[],
|
|
11
11
|
pagination?: PaginationConfig
|
|
12
|
-
): Promise<
|
|
12
|
+
): Promise<T[]> {
|
|
13
13
|
const docs = initial.slice();
|
|
14
14
|
let current: string | null = nextUrl;
|
|
15
15
|
let pageCount = 0;
|
|
@@ -22,21 +22,24 @@ export async function fetchAllPages(
|
|
|
22
22
|
if (maxPages != null && pageCount >= maxPages) break;
|
|
23
23
|
if (maxWaitTime != null && (Date.now() - started) / 1000 > maxWaitTime) break;
|
|
24
24
|
|
|
25
|
-
let payload: { success: boolean; next?: string | null; data?:
|
|
25
|
+
let payload: { success: boolean; next?: string | null; data?: T[] | { pages?: T[]; next?: string | null } } | null = null;
|
|
26
26
|
try {
|
|
27
|
-
const res = await http.get<{ success: boolean; next?: string | null; data?:
|
|
27
|
+
const res = await http.get<{ success: boolean; next?: string | null; data?: T[] | { pages?: T[]; next?: string | null } }>(current);
|
|
28
28
|
payload = res.data;
|
|
29
29
|
} catch {
|
|
30
30
|
break; // axios rejects on non-2xx; stop pagination gracefully
|
|
31
31
|
}
|
|
32
32
|
if (!payload?.success) break;
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
const pageData = Array.isArray(payload.data)
|
|
35
|
+
? payload.data
|
|
36
|
+
: payload.data?.pages || [];
|
|
37
|
+
for (const d of pageData) {
|
|
35
38
|
if (maxResults != null && docs.length >= maxResults) break;
|
|
36
|
-
docs.push(d as
|
|
39
|
+
docs.push(d as T);
|
|
37
40
|
}
|
|
38
41
|
if (maxResults != null && docs.length >= maxResults) break;
|
|
39
|
-
current = (payload.next ?? null) as string | null;
|
|
42
|
+
current = (payload.next ?? (Array.isArray(payload.data) ? null : payload.data?.next) ?? null) as string | null;
|
|
40
43
|
pageCount += 1;
|
|
41
44
|
}
|
|
42
45
|
return docs;
|
|
@@ -4,6 +4,9 @@ import {
|
|
|
4
4
|
type JsonFormat,
|
|
5
5
|
type ParseFormatOption,
|
|
6
6
|
type ParseOptions,
|
|
7
|
+
type QuestionFormat,
|
|
8
|
+
type HighlightsFormat,
|
|
9
|
+
type QueryFormat,
|
|
7
10
|
type ScrapeOptions,
|
|
8
11
|
type ScreenshotFormat,
|
|
9
12
|
} from "../types";
|
|
@@ -49,6 +52,30 @@ export function ensureValidFormats(formats?: FormatOption[]): void {
|
|
|
49
52
|
}
|
|
50
53
|
continue;
|
|
51
54
|
}
|
|
55
|
+
if ((fmt as QuestionFormat).type === "question") {
|
|
56
|
+
const q = fmt as QuestionFormat;
|
|
57
|
+
if (typeof q.question !== "string" || q.question.trim().length === 0) {
|
|
58
|
+
throw new Error("question format requires a non-empty 'question' string");
|
|
59
|
+
}
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if ((fmt as HighlightsFormat).type === "highlights") {
|
|
63
|
+
const h = fmt as HighlightsFormat;
|
|
64
|
+
if (typeof h.query !== "string" || h.query.trim().length === 0) {
|
|
65
|
+
throw new Error("highlights format requires a non-empty 'query' string");
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if ((fmt as QueryFormat).type === "query") {
|
|
70
|
+
const q = fmt as QueryFormat;
|
|
71
|
+
if (typeof q.prompt !== "string" || q.prompt.trim().length === 0) {
|
|
72
|
+
throw new Error("query format requires a non-empty 'prompt' string");
|
|
73
|
+
}
|
|
74
|
+
if (q.mode != null && q.mode !== "freeform" && q.mode !== "directQuote") {
|
|
75
|
+
throw new Error("query format mode must be 'freeform' or 'directQuote'");
|
|
76
|
+
}
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
52
79
|
if ((fmt as ScreenshotFormat).type === "screenshot") {
|
|
53
80
|
// no-op; already camelCase; validate numeric fields if present
|
|
54
81
|
const s = fmt as ScreenshotFormat;
|
|
@@ -116,6 +143,31 @@ export function ensureValidParseFormats(formats?: ParseFormatOption[]): void {
|
|
|
116
143
|
"The SDK will automatically convert Zod schemas to JSON Schema format."
|
|
117
144
|
);
|
|
118
145
|
}
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if ((fmt as QuestionFormat).type === "question") {
|
|
150
|
+
const q = fmt as QuestionFormat;
|
|
151
|
+
if (typeof q.question !== "string" || q.question.trim().length === 0) {
|
|
152
|
+
throw new Error("question format requires a non-empty 'question' string");
|
|
153
|
+
}
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if ((fmt as HighlightsFormat).type === "highlights") {
|
|
157
|
+
const h = fmt as HighlightsFormat;
|
|
158
|
+
if (typeof h.query !== "string" || h.query.trim().length === 0) {
|
|
159
|
+
throw new Error("highlights format requires a non-empty 'query' string");
|
|
160
|
+
}
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if ((fmt as QueryFormat).type === "query") {
|
|
164
|
+
const q = fmt as QueryFormat;
|
|
165
|
+
if (typeof q.prompt !== "string" || q.prompt.trim().length === 0) {
|
|
166
|
+
throw new Error("query format requires a non-empty 'prompt' string");
|
|
167
|
+
}
|
|
168
|
+
if (q.mode != null && q.mode !== "freeform" && q.mode !== "directQuote") {
|
|
169
|
+
throw new Error("query format mode must be 'freeform' or 'directQuote'");
|
|
170
|
+
}
|
|
119
171
|
}
|
|
120
172
|
}
|
|
121
173
|
}
|