firecrawl 4.21.1 → 4.22.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/src/v2/types.ts CHANGED
@@ -606,6 +606,154 @@ export interface MapOptions {
606
606
  location?: LocationConfig;
607
607
  }
608
608
 
609
+ export interface MonitorSchedule {
610
+ cron: string;
611
+ timezone?: string;
612
+ }
613
+
614
+ export interface MonitorEmailNotification {
615
+ enabled?: boolean;
616
+ recipients?: string[];
617
+ includeDiffs?: boolean;
618
+ }
619
+
620
+ export interface MonitorNotification {
621
+ email?: MonitorEmailNotification;
622
+ }
623
+
624
+ export interface MonitorWebhookConfig {
625
+ url: string;
626
+ headers?: Record<string, string>;
627
+ metadata?: Record<string, string>;
628
+ events?: string[];
629
+ }
630
+
631
+ export interface MonitorScrapeTarget {
632
+ id?: string;
633
+ type: 'scrape';
634
+ urls: string[];
635
+ scrapeOptions?: ScrapeOptions;
636
+ }
637
+
638
+ export interface MonitorCrawlTarget {
639
+ id?: string;
640
+ type: 'crawl';
641
+ url: string;
642
+ crawlOptions?: CrawlOptions;
643
+ scrapeOptions?: ScrapeOptions;
644
+ }
645
+
646
+ export type MonitorTarget = MonitorScrapeTarget | MonitorCrawlTarget;
647
+
648
+ export interface CreateMonitorRequest {
649
+ name: string;
650
+ schedule: MonitorSchedule;
651
+ webhook?: MonitorWebhookConfig;
652
+ notification?: MonitorNotification;
653
+ targets: MonitorTarget[];
654
+ retentionDays?: number;
655
+ }
656
+
657
+ export interface UpdateMonitorRequest {
658
+ name?: string;
659
+ status?: 'active' | 'paused';
660
+ schedule?: MonitorSchedule;
661
+ webhook?: MonitorWebhookConfig | null;
662
+ notification?: MonitorNotification | null;
663
+ targets?: MonitorTarget[];
664
+ retentionDays?: number;
665
+ }
666
+
667
+ export interface MonitorSummary {
668
+ totalPages: number;
669
+ same: number;
670
+ changed: number;
671
+ new: number;
672
+ removed: number;
673
+ error: number;
674
+ }
675
+
676
+ export interface Monitor {
677
+ id: string;
678
+ name: string;
679
+ status: 'active' | 'paused' | 'deleted';
680
+ schedule: MonitorSchedule;
681
+ nextRunAt?: string | null;
682
+ lastRunAt?: string | null;
683
+ currentCheckId?: string | null;
684
+ targets: MonitorTarget[];
685
+ webhook?: MonitorWebhookConfig | null;
686
+ notification?: MonitorNotification | null;
687
+ retentionDays: number;
688
+ estimatedCreditsPerMonth?: number | null;
689
+ lastCheckSummary?: MonitorSummary | null;
690
+ createdAt: string;
691
+ updatedAt: string;
692
+ }
693
+
694
+ export interface MonitorCheck {
695
+ id: string;
696
+ monitorId: string;
697
+ status:
698
+ | 'queued'
699
+ | 'running'
700
+ | 'completed'
701
+ | 'failed'
702
+ | 'partial'
703
+ | 'skipped_overlap';
704
+ trigger: 'scheduled' | 'manual';
705
+ scheduledFor?: string | null;
706
+ startedAt?: string | null;
707
+ finishedAt?: string | null;
708
+ estimatedCredits?: number | null;
709
+ reservedCredits?: number | null;
710
+ actualCredits?: number | null;
711
+ billingStatus:
712
+ | 'not_applicable'
713
+ | 'reserved'
714
+ | 'confirmed'
715
+ | 'released'
716
+ | 'failed';
717
+ summary: MonitorSummary;
718
+ targetResults?: unknown;
719
+ notificationStatus?: unknown;
720
+ error?: string | null;
721
+ createdAt: string;
722
+ updatedAt: string;
723
+ }
724
+
725
+ export interface MonitorCheckPage {
726
+ id: string;
727
+ targetId: string;
728
+ url: string;
729
+ status: 'same' | 'new' | 'changed' | 'removed' | 'error';
730
+ previousScrapeId?: string | null;
731
+ currentScrapeId?: string | null;
732
+ statusCode?: number | null;
733
+ error?: string | null;
734
+ metadata?: unknown;
735
+ diff?: unknown;
736
+ createdAt: string;
737
+ }
738
+
739
+ export interface MonitorCheckDetail extends MonitorCheck {
740
+ pages: MonitorCheckPage[];
741
+ next?: string | null;
742
+ }
743
+
744
+ export interface ListMonitorsOptions {
745
+ limit?: number;
746
+ offset?: number;
747
+ }
748
+
749
+ export type ListMonitorChecksOptions = ListMonitorsOptions;
750
+
751
+ export type GetMonitorCheckOptions = PaginationConfig & {
752
+ limit?: number;
753
+ skip?: number;
754
+ status?: MonitorCheckPage["status"];
755
+ };
756
+
609
757
  export interface ExtractResponse {
610
758
  success?: boolean;
611
759
  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` cursors and aggregate documents with limits.
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: Document[],
10
+ initial: T[],
11
11
  pagination?: PaginationConfig
12
- ): Promise<Document[]> {
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?: Document[] } | null = null;
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?: Document[] }>(current);
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
- for (const d of payload.data || []) {
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 Document);
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;