@dealcrawl/sdk 2.11.1 → 2.12.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 +40 -0
- package/dist/index.d.mts +189 -0
- package/dist/index.d.ts +189 -0
- package/dist/index.js +194 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +194 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,6 +6,46 @@ Official TypeScript SDK for the DealCrawl web scraping and crawling API.
|
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
|
|
9
|
+
## What's New in v2.12.0 (January 2026) ✨
|
|
10
|
+
|
|
11
|
+
### New Methods - 100% API Coverage
|
|
12
|
+
|
|
13
|
+
All missing API endpoints now have SDK methods (completes the 87% → 100% alignment):
|
|
14
|
+
|
|
15
|
+
**Status Resource (`client.status.*`)**
|
|
16
|
+
|
|
17
|
+
- `getJobErrors(jobId, options?)` - Get job errors without loading full results (useful for debugging large crawls)
|
|
18
|
+
|
|
19
|
+
**Data Resource (`client.data.*`)**
|
|
20
|
+
|
|
21
|
+
- `getJob(jobId)` - Get full job details with result
|
|
22
|
+
- `getJobResult(jobId)` - Get only the result of a completed job
|
|
23
|
+
- `exportJob(jobId, format)` - Export job in multiple formats (json, markdown, llm, csv)
|
|
24
|
+
|
|
25
|
+
**Webhooks Resource (`client.webhooks.*`)**
|
|
26
|
+
|
|
27
|
+
- `rotateSecret(webhookId, options)` - Rotate webhook secret with grace period support
|
|
28
|
+
- `getSecretStatus(webhookId)` - Check secret version and grace period status
|
|
29
|
+
- `verifySignature(options)` - Verify webhook signature and replay protection
|
|
30
|
+
|
|
31
|
+
### Examples
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// Get job errors for debugging
|
|
35
|
+
const errors = await client.status.getJobErrors("job_abc123", { limit: 50 });
|
|
36
|
+
|
|
37
|
+
// Export crawl results as Markdown
|
|
38
|
+
const markdown = await client.data.exportJob("crawl_123", "markdown");
|
|
39
|
+
|
|
40
|
+
// Rotate webhook secret with 24h grace period
|
|
41
|
+
await client.webhooks.rotateSecret("webhook_abc", {
|
|
42
|
+
newSecret: "new-secure-key",
|
|
43
|
+
gracePeriodHours: 24
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
9
49
|
## What's New in v2.11.1 (January 2026) 🐛
|
|
10
50
|
|
|
11
51
|
### Bug Fixes
|
package/dist/index.d.mts
CHANGED
|
@@ -690,6 +690,22 @@ interface CancelJobResponse {
|
|
|
690
690
|
jobId: string;
|
|
691
691
|
message: string;
|
|
692
692
|
}
|
|
693
|
+
/** Job error entry */
|
|
694
|
+
interface JobErrorEntry {
|
|
695
|
+
url?: string;
|
|
696
|
+
error: string;
|
|
697
|
+
timestamp?: string;
|
|
698
|
+
}
|
|
699
|
+
/** Job errors response */
|
|
700
|
+
interface JobErrorsResponse {
|
|
701
|
+
data: JobErrorEntry[];
|
|
702
|
+
pagination: PaginationInfo;
|
|
703
|
+
meta?: {
|
|
704
|
+
jobId: string;
|
|
705
|
+
status?: JobStatus$1;
|
|
706
|
+
offset?: number;
|
|
707
|
+
};
|
|
708
|
+
}
|
|
693
709
|
/** Job summary in list */
|
|
694
710
|
interface JobSummary {
|
|
695
711
|
id: string;
|
|
@@ -769,6 +785,32 @@ interface ClientStatsResponse {
|
|
|
769
785
|
}>;
|
|
770
786
|
};
|
|
771
787
|
}
|
|
788
|
+
/** Full job details response */
|
|
789
|
+
interface JobDetailsResponse {
|
|
790
|
+
id: string;
|
|
791
|
+
type: "scrape" | "crawl" | "dork" | "extract";
|
|
792
|
+
status: JobStatus$1;
|
|
793
|
+
input: Record<string, unknown>;
|
|
794
|
+
result?: unknown;
|
|
795
|
+
progress?: number;
|
|
796
|
+
error?: string;
|
|
797
|
+
dealsFound?: number;
|
|
798
|
+
avgDealScore?: number;
|
|
799
|
+
highestDealScore?: number;
|
|
800
|
+
checkpoint?: CheckpointInfo;
|
|
801
|
+
createdAt: string;
|
|
802
|
+
updatedAt: string;
|
|
803
|
+
completedAt?: string;
|
|
804
|
+
}
|
|
805
|
+
/** Job result response */
|
|
806
|
+
interface JobResultResponse {
|
|
807
|
+
jobId: string;
|
|
808
|
+
status: "completed";
|
|
809
|
+
result: unknown;
|
|
810
|
+
completedAt?: string;
|
|
811
|
+
}
|
|
812
|
+
/** Job export response (string for CSV/Markdown/LLM, object for JSON) */
|
|
813
|
+
type JobExportResponse = string | Record<string, unknown>;
|
|
772
814
|
/** Webhook in list */
|
|
773
815
|
interface WebhookItem {
|
|
774
816
|
id: string;
|
|
@@ -824,6 +866,35 @@ interface TestWebhookResponse {
|
|
|
824
866
|
responseTime?: number;
|
|
825
867
|
error?: string;
|
|
826
868
|
}
|
|
869
|
+
/** Rotate webhook secret response */
|
|
870
|
+
interface RotateSecretResponse {
|
|
871
|
+
success: boolean;
|
|
872
|
+
webhookId: string;
|
|
873
|
+
secretVersion: number;
|
|
874
|
+
previousSecretValidUntil: string;
|
|
875
|
+
gracePeriodHours: number;
|
|
876
|
+
message: string;
|
|
877
|
+
}
|
|
878
|
+
/** Webhook secret status response */
|
|
879
|
+
interface SecretStatusResponse {
|
|
880
|
+
webhookId: string;
|
|
881
|
+
hasSecret: boolean;
|
|
882
|
+
secretVersion: number;
|
|
883
|
+
lastRotatedAt?: string;
|
|
884
|
+
gracePeriod?: {
|
|
885
|
+
active: boolean;
|
|
886
|
+
previousVersion: number;
|
|
887
|
+
expiresAt: string;
|
|
888
|
+
} | null;
|
|
889
|
+
}
|
|
890
|
+
/** Verify webhook signature response */
|
|
891
|
+
interface VerifyWebhookResponse {
|
|
892
|
+
valid: boolean;
|
|
893
|
+
webhookId?: string;
|
|
894
|
+
message: string;
|
|
895
|
+
error?: string;
|
|
896
|
+
reason?: string;
|
|
897
|
+
}
|
|
827
898
|
/** API key info (safe, without secret) */
|
|
828
899
|
interface ApiKeyInfo {
|
|
829
900
|
id: string;
|
|
@@ -2645,6 +2716,47 @@ declare class DataResource {
|
|
|
2645
2716
|
* ```
|
|
2646
2717
|
*/
|
|
2647
2718
|
getRecentJobs(limit?: number): Promise<ListJobsResponse>;
|
|
2719
|
+
/**
|
|
2720
|
+
* Get full job details with result
|
|
2721
|
+
*
|
|
2722
|
+
* @example
|
|
2723
|
+
* ```ts
|
|
2724
|
+
* const job = await client.data.getJob("job_abc123");
|
|
2725
|
+
* console.log(job.result);
|
|
2726
|
+
* console.log(job.dealsFound);
|
|
2727
|
+
* ```
|
|
2728
|
+
*/
|
|
2729
|
+
getJob(jobId: string): Promise<JobDetailsResponse>;
|
|
2730
|
+
/**
|
|
2731
|
+
* Get only the result of a completed job
|
|
2732
|
+
*
|
|
2733
|
+
* @example
|
|
2734
|
+
* ```ts
|
|
2735
|
+
* const result = await client.data.getJobResult("job_abc123");
|
|
2736
|
+
* console.log(result.result);
|
|
2737
|
+
* ```
|
|
2738
|
+
*/
|
|
2739
|
+
getJobResult(jobId: string): Promise<JobResultResponse>;
|
|
2740
|
+
/**
|
|
2741
|
+
* Export job results in various formats
|
|
2742
|
+
* Supports: json, markdown, llm, csv
|
|
2743
|
+
*
|
|
2744
|
+
* @example
|
|
2745
|
+
* ```ts
|
|
2746
|
+
* // Export as JSON
|
|
2747
|
+
* const jsonData = await client.data.exportJob("job_abc123", "json");
|
|
2748
|
+
*
|
|
2749
|
+
* // Export as Markdown
|
|
2750
|
+
* const markdown = await client.data.exportJob("job_abc123", "markdown");
|
|
2751
|
+
*
|
|
2752
|
+
* // Export as LLM-optimized format
|
|
2753
|
+
* const llmText = await client.data.exportJob("job_abc123", "llm");
|
|
2754
|
+
*
|
|
2755
|
+
* // Export as CSV
|
|
2756
|
+
* const csv = await client.data.exportJob("job_abc123", "csv");
|
|
2757
|
+
* ```
|
|
2758
|
+
*/
|
|
2759
|
+
exportJob(jobId: string, format?: "json" | "markdown" | "llm" | "csv"): Promise<JobExportResponse>;
|
|
2648
2760
|
/**
|
|
2649
2761
|
* List all deals
|
|
2650
2762
|
*
|
|
@@ -3537,6 +3649,24 @@ declare class StatusResource {
|
|
|
3537
3649
|
* ```
|
|
3538
3650
|
*/
|
|
3539
3651
|
getMetrics(jobId: string): Promise<JobMetricsResponse>;
|
|
3652
|
+
/**
|
|
3653
|
+
* Get errors from a job
|
|
3654
|
+
* Useful for debugging large crawls without loading full results
|
|
3655
|
+
*
|
|
3656
|
+
* @example
|
|
3657
|
+
* ```ts
|
|
3658
|
+
* const errors = await client.status.getJobErrors("job_abc123", {
|
|
3659
|
+
* limit: 50,
|
|
3660
|
+
* offset: 0
|
|
3661
|
+
* });
|
|
3662
|
+
* console.log(errors.data);
|
|
3663
|
+
* console.log(errors.pagination.total);
|
|
3664
|
+
* ```
|
|
3665
|
+
*/
|
|
3666
|
+
getJobErrors(jobId: string, options?: {
|
|
3667
|
+
limit?: number;
|
|
3668
|
+
offset?: number;
|
|
3669
|
+
}): Promise<JobErrorsResponse>;
|
|
3540
3670
|
/**
|
|
3541
3671
|
* Cancel a pending or active job
|
|
3542
3672
|
*
|
|
@@ -3701,6 +3831,65 @@ declare class WebhooksResource {
|
|
|
3701
3831
|
* ```
|
|
3702
3832
|
*/
|
|
3703
3833
|
getByEvent(event: CreateWebhookOptions["event"]): Promise<WebhookItem[]>;
|
|
3834
|
+
/**
|
|
3835
|
+
* Rotate webhook secret
|
|
3836
|
+
* Rotates the secret while keeping the old one valid during grace period
|
|
3837
|
+
*
|
|
3838
|
+
* @example
|
|
3839
|
+
* ```ts
|
|
3840
|
+
* const result = await client.webhooks.rotateSecret("webhook_abc123", {
|
|
3841
|
+
* newSecret: "new-secure-secret-key",
|
|
3842
|
+
* gracePeriodHours: 24
|
|
3843
|
+
* });
|
|
3844
|
+
* console.log(result.secretVersion);
|
|
3845
|
+
* console.log(result.previousSecretValidUntil);
|
|
3846
|
+
* ```
|
|
3847
|
+
*/
|
|
3848
|
+
rotateSecret(webhookId: string, options: {
|
|
3849
|
+
newSecret: string;
|
|
3850
|
+
gracePeriodHours?: number;
|
|
3851
|
+
}): Promise<RotateSecretResponse>;
|
|
3852
|
+
/**
|
|
3853
|
+
* Get webhook secret rotation status
|
|
3854
|
+
* Check current secret version and grace period status
|
|
3855
|
+
*
|
|
3856
|
+
* @example
|
|
3857
|
+
* ```ts
|
|
3858
|
+
* const status = await client.webhooks.getSecretStatus("webhook_abc123");
|
|
3859
|
+
* console.log(status.secretVersion);
|
|
3860
|
+
* if (status.gracePeriod?.active) {
|
|
3861
|
+
* console.log(`Grace period expires: ${status.gracePeriod.expiresAt}`);
|
|
3862
|
+
* }
|
|
3863
|
+
* ```
|
|
3864
|
+
*/
|
|
3865
|
+
getSecretStatus(webhookId: string): Promise<SecretStatusResponse>;
|
|
3866
|
+
/**
|
|
3867
|
+
* Verify webhook signature and replay protection
|
|
3868
|
+
* Validates signature, timestamp, and nonce from received webhook
|
|
3869
|
+
*
|
|
3870
|
+
* @example
|
|
3871
|
+
* ```ts
|
|
3872
|
+
* const isValid = await client.webhooks.verifySignature({
|
|
3873
|
+
* webhookId: "webhook_abc123",
|
|
3874
|
+
* payload: receivedPayload,
|
|
3875
|
+
* signature: headers["x-dealcrawl-signature"],
|
|
3876
|
+
* timestamp: parseInt(headers["x-dealcrawl-timestamp"]),
|
|
3877
|
+
* nonce: headers["x-dealcrawl-nonce"]
|
|
3878
|
+
* });
|
|
3879
|
+
* if (isValid.valid) {
|
|
3880
|
+
* console.log("Webhook is valid");
|
|
3881
|
+
* } else {
|
|
3882
|
+
* console.log(`Invalid: ${isValid.error}`);
|
|
3883
|
+
* }
|
|
3884
|
+
* ```
|
|
3885
|
+
*/
|
|
3886
|
+
verifySignature(options: {
|
|
3887
|
+
webhookId: string;
|
|
3888
|
+
payload: Record<string, unknown>;
|
|
3889
|
+
signature: string;
|
|
3890
|
+
timestamp: number;
|
|
3891
|
+
nonce: string;
|
|
3892
|
+
}): Promise<VerifyWebhookResponse>;
|
|
3704
3893
|
}
|
|
3705
3894
|
|
|
3706
3895
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -690,6 +690,22 @@ interface CancelJobResponse {
|
|
|
690
690
|
jobId: string;
|
|
691
691
|
message: string;
|
|
692
692
|
}
|
|
693
|
+
/** Job error entry */
|
|
694
|
+
interface JobErrorEntry {
|
|
695
|
+
url?: string;
|
|
696
|
+
error: string;
|
|
697
|
+
timestamp?: string;
|
|
698
|
+
}
|
|
699
|
+
/** Job errors response */
|
|
700
|
+
interface JobErrorsResponse {
|
|
701
|
+
data: JobErrorEntry[];
|
|
702
|
+
pagination: PaginationInfo;
|
|
703
|
+
meta?: {
|
|
704
|
+
jobId: string;
|
|
705
|
+
status?: JobStatus$1;
|
|
706
|
+
offset?: number;
|
|
707
|
+
};
|
|
708
|
+
}
|
|
693
709
|
/** Job summary in list */
|
|
694
710
|
interface JobSummary {
|
|
695
711
|
id: string;
|
|
@@ -769,6 +785,32 @@ interface ClientStatsResponse {
|
|
|
769
785
|
}>;
|
|
770
786
|
};
|
|
771
787
|
}
|
|
788
|
+
/** Full job details response */
|
|
789
|
+
interface JobDetailsResponse {
|
|
790
|
+
id: string;
|
|
791
|
+
type: "scrape" | "crawl" | "dork" | "extract";
|
|
792
|
+
status: JobStatus$1;
|
|
793
|
+
input: Record<string, unknown>;
|
|
794
|
+
result?: unknown;
|
|
795
|
+
progress?: number;
|
|
796
|
+
error?: string;
|
|
797
|
+
dealsFound?: number;
|
|
798
|
+
avgDealScore?: number;
|
|
799
|
+
highestDealScore?: number;
|
|
800
|
+
checkpoint?: CheckpointInfo;
|
|
801
|
+
createdAt: string;
|
|
802
|
+
updatedAt: string;
|
|
803
|
+
completedAt?: string;
|
|
804
|
+
}
|
|
805
|
+
/** Job result response */
|
|
806
|
+
interface JobResultResponse {
|
|
807
|
+
jobId: string;
|
|
808
|
+
status: "completed";
|
|
809
|
+
result: unknown;
|
|
810
|
+
completedAt?: string;
|
|
811
|
+
}
|
|
812
|
+
/** Job export response (string for CSV/Markdown/LLM, object for JSON) */
|
|
813
|
+
type JobExportResponse = string | Record<string, unknown>;
|
|
772
814
|
/** Webhook in list */
|
|
773
815
|
interface WebhookItem {
|
|
774
816
|
id: string;
|
|
@@ -824,6 +866,35 @@ interface TestWebhookResponse {
|
|
|
824
866
|
responseTime?: number;
|
|
825
867
|
error?: string;
|
|
826
868
|
}
|
|
869
|
+
/** Rotate webhook secret response */
|
|
870
|
+
interface RotateSecretResponse {
|
|
871
|
+
success: boolean;
|
|
872
|
+
webhookId: string;
|
|
873
|
+
secretVersion: number;
|
|
874
|
+
previousSecretValidUntil: string;
|
|
875
|
+
gracePeriodHours: number;
|
|
876
|
+
message: string;
|
|
877
|
+
}
|
|
878
|
+
/** Webhook secret status response */
|
|
879
|
+
interface SecretStatusResponse {
|
|
880
|
+
webhookId: string;
|
|
881
|
+
hasSecret: boolean;
|
|
882
|
+
secretVersion: number;
|
|
883
|
+
lastRotatedAt?: string;
|
|
884
|
+
gracePeriod?: {
|
|
885
|
+
active: boolean;
|
|
886
|
+
previousVersion: number;
|
|
887
|
+
expiresAt: string;
|
|
888
|
+
} | null;
|
|
889
|
+
}
|
|
890
|
+
/** Verify webhook signature response */
|
|
891
|
+
interface VerifyWebhookResponse {
|
|
892
|
+
valid: boolean;
|
|
893
|
+
webhookId?: string;
|
|
894
|
+
message: string;
|
|
895
|
+
error?: string;
|
|
896
|
+
reason?: string;
|
|
897
|
+
}
|
|
827
898
|
/** API key info (safe, without secret) */
|
|
828
899
|
interface ApiKeyInfo {
|
|
829
900
|
id: string;
|
|
@@ -2645,6 +2716,47 @@ declare class DataResource {
|
|
|
2645
2716
|
* ```
|
|
2646
2717
|
*/
|
|
2647
2718
|
getRecentJobs(limit?: number): Promise<ListJobsResponse>;
|
|
2719
|
+
/**
|
|
2720
|
+
* Get full job details with result
|
|
2721
|
+
*
|
|
2722
|
+
* @example
|
|
2723
|
+
* ```ts
|
|
2724
|
+
* const job = await client.data.getJob("job_abc123");
|
|
2725
|
+
* console.log(job.result);
|
|
2726
|
+
* console.log(job.dealsFound);
|
|
2727
|
+
* ```
|
|
2728
|
+
*/
|
|
2729
|
+
getJob(jobId: string): Promise<JobDetailsResponse>;
|
|
2730
|
+
/**
|
|
2731
|
+
* Get only the result of a completed job
|
|
2732
|
+
*
|
|
2733
|
+
* @example
|
|
2734
|
+
* ```ts
|
|
2735
|
+
* const result = await client.data.getJobResult("job_abc123");
|
|
2736
|
+
* console.log(result.result);
|
|
2737
|
+
* ```
|
|
2738
|
+
*/
|
|
2739
|
+
getJobResult(jobId: string): Promise<JobResultResponse>;
|
|
2740
|
+
/**
|
|
2741
|
+
* Export job results in various formats
|
|
2742
|
+
* Supports: json, markdown, llm, csv
|
|
2743
|
+
*
|
|
2744
|
+
* @example
|
|
2745
|
+
* ```ts
|
|
2746
|
+
* // Export as JSON
|
|
2747
|
+
* const jsonData = await client.data.exportJob("job_abc123", "json");
|
|
2748
|
+
*
|
|
2749
|
+
* // Export as Markdown
|
|
2750
|
+
* const markdown = await client.data.exportJob("job_abc123", "markdown");
|
|
2751
|
+
*
|
|
2752
|
+
* // Export as LLM-optimized format
|
|
2753
|
+
* const llmText = await client.data.exportJob("job_abc123", "llm");
|
|
2754
|
+
*
|
|
2755
|
+
* // Export as CSV
|
|
2756
|
+
* const csv = await client.data.exportJob("job_abc123", "csv");
|
|
2757
|
+
* ```
|
|
2758
|
+
*/
|
|
2759
|
+
exportJob(jobId: string, format?: "json" | "markdown" | "llm" | "csv"): Promise<JobExportResponse>;
|
|
2648
2760
|
/**
|
|
2649
2761
|
* List all deals
|
|
2650
2762
|
*
|
|
@@ -3537,6 +3649,24 @@ declare class StatusResource {
|
|
|
3537
3649
|
* ```
|
|
3538
3650
|
*/
|
|
3539
3651
|
getMetrics(jobId: string): Promise<JobMetricsResponse>;
|
|
3652
|
+
/**
|
|
3653
|
+
* Get errors from a job
|
|
3654
|
+
* Useful for debugging large crawls without loading full results
|
|
3655
|
+
*
|
|
3656
|
+
* @example
|
|
3657
|
+
* ```ts
|
|
3658
|
+
* const errors = await client.status.getJobErrors("job_abc123", {
|
|
3659
|
+
* limit: 50,
|
|
3660
|
+
* offset: 0
|
|
3661
|
+
* });
|
|
3662
|
+
* console.log(errors.data);
|
|
3663
|
+
* console.log(errors.pagination.total);
|
|
3664
|
+
* ```
|
|
3665
|
+
*/
|
|
3666
|
+
getJobErrors(jobId: string, options?: {
|
|
3667
|
+
limit?: number;
|
|
3668
|
+
offset?: number;
|
|
3669
|
+
}): Promise<JobErrorsResponse>;
|
|
3540
3670
|
/**
|
|
3541
3671
|
* Cancel a pending or active job
|
|
3542
3672
|
*
|
|
@@ -3701,6 +3831,65 @@ declare class WebhooksResource {
|
|
|
3701
3831
|
* ```
|
|
3702
3832
|
*/
|
|
3703
3833
|
getByEvent(event: CreateWebhookOptions["event"]): Promise<WebhookItem[]>;
|
|
3834
|
+
/**
|
|
3835
|
+
* Rotate webhook secret
|
|
3836
|
+
* Rotates the secret while keeping the old one valid during grace period
|
|
3837
|
+
*
|
|
3838
|
+
* @example
|
|
3839
|
+
* ```ts
|
|
3840
|
+
* const result = await client.webhooks.rotateSecret("webhook_abc123", {
|
|
3841
|
+
* newSecret: "new-secure-secret-key",
|
|
3842
|
+
* gracePeriodHours: 24
|
|
3843
|
+
* });
|
|
3844
|
+
* console.log(result.secretVersion);
|
|
3845
|
+
* console.log(result.previousSecretValidUntil);
|
|
3846
|
+
* ```
|
|
3847
|
+
*/
|
|
3848
|
+
rotateSecret(webhookId: string, options: {
|
|
3849
|
+
newSecret: string;
|
|
3850
|
+
gracePeriodHours?: number;
|
|
3851
|
+
}): Promise<RotateSecretResponse>;
|
|
3852
|
+
/**
|
|
3853
|
+
* Get webhook secret rotation status
|
|
3854
|
+
* Check current secret version and grace period status
|
|
3855
|
+
*
|
|
3856
|
+
* @example
|
|
3857
|
+
* ```ts
|
|
3858
|
+
* const status = await client.webhooks.getSecretStatus("webhook_abc123");
|
|
3859
|
+
* console.log(status.secretVersion);
|
|
3860
|
+
* if (status.gracePeriod?.active) {
|
|
3861
|
+
* console.log(`Grace period expires: ${status.gracePeriod.expiresAt}`);
|
|
3862
|
+
* }
|
|
3863
|
+
* ```
|
|
3864
|
+
*/
|
|
3865
|
+
getSecretStatus(webhookId: string): Promise<SecretStatusResponse>;
|
|
3866
|
+
/**
|
|
3867
|
+
* Verify webhook signature and replay protection
|
|
3868
|
+
* Validates signature, timestamp, and nonce from received webhook
|
|
3869
|
+
*
|
|
3870
|
+
* @example
|
|
3871
|
+
* ```ts
|
|
3872
|
+
* const isValid = await client.webhooks.verifySignature({
|
|
3873
|
+
* webhookId: "webhook_abc123",
|
|
3874
|
+
* payload: receivedPayload,
|
|
3875
|
+
* signature: headers["x-dealcrawl-signature"],
|
|
3876
|
+
* timestamp: parseInt(headers["x-dealcrawl-timestamp"]),
|
|
3877
|
+
* nonce: headers["x-dealcrawl-nonce"]
|
|
3878
|
+
* });
|
|
3879
|
+
* if (isValid.valid) {
|
|
3880
|
+
* console.log("Webhook is valid");
|
|
3881
|
+
* } else {
|
|
3882
|
+
* console.log(`Invalid: ${isValid.error}`);
|
|
3883
|
+
* }
|
|
3884
|
+
* ```
|
|
3885
|
+
*/
|
|
3886
|
+
verifySignature(options: {
|
|
3887
|
+
webhookId: string;
|
|
3888
|
+
payload: Record<string, unknown>;
|
|
3889
|
+
signature: string;
|
|
3890
|
+
timestamp: number;
|
|
3891
|
+
nonce: string;
|
|
3892
|
+
}): Promise<VerifyWebhookResponse>;
|
|
3704
3893
|
}
|
|
3705
3894
|
|
|
3706
3895
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1637,6 +1637,75 @@ var DataResource = class {
|
|
|
1637
1637
|
sortOrder: "desc"
|
|
1638
1638
|
});
|
|
1639
1639
|
}
|
|
1640
|
+
/**
|
|
1641
|
+
* Get full job details with result
|
|
1642
|
+
*
|
|
1643
|
+
* @example
|
|
1644
|
+
* ```ts
|
|
1645
|
+
* const job = await client.data.getJob("job_abc123");
|
|
1646
|
+
* console.log(job.result);
|
|
1647
|
+
* console.log(job.dealsFound);
|
|
1648
|
+
* ```
|
|
1649
|
+
*/
|
|
1650
|
+
async getJob(jobId) {
|
|
1651
|
+
if (!jobId || !jobId.trim()) {
|
|
1652
|
+
throw new Error("jobId is required and cannot be empty");
|
|
1653
|
+
}
|
|
1654
|
+
const result = await get(
|
|
1655
|
+
this.ctx,
|
|
1656
|
+
`/v1/data/jobs/${jobId}`
|
|
1657
|
+
);
|
|
1658
|
+
return result.data;
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Get only the result of a completed job
|
|
1662
|
+
*
|
|
1663
|
+
* @example
|
|
1664
|
+
* ```ts
|
|
1665
|
+
* const result = await client.data.getJobResult("job_abc123");
|
|
1666
|
+
* console.log(result.result);
|
|
1667
|
+
* ```
|
|
1668
|
+
*/
|
|
1669
|
+
async getJobResult(jobId) {
|
|
1670
|
+
if (!jobId || !jobId.trim()) {
|
|
1671
|
+
throw new Error("jobId is required and cannot be empty");
|
|
1672
|
+
}
|
|
1673
|
+
const result = await get(
|
|
1674
|
+
this.ctx,
|
|
1675
|
+
`/v1/data/jobs/${jobId}/result`
|
|
1676
|
+
);
|
|
1677
|
+
return result.data;
|
|
1678
|
+
}
|
|
1679
|
+
/**
|
|
1680
|
+
* Export job results in various formats
|
|
1681
|
+
* Supports: json, markdown, llm, csv
|
|
1682
|
+
*
|
|
1683
|
+
* @example
|
|
1684
|
+
* ```ts
|
|
1685
|
+
* // Export as JSON
|
|
1686
|
+
* const jsonData = await client.data.exportJob("job_abc123", "json");
|
|
1687
|
+
*
|
|
1688
|
+
* // Export as Markdown
|
|
1689
|
+
* const markdown = await client.data.exportJob("job_abc123", "markdown");
|
|
1690
|
+
*
|
|
1691
|
+
* // Export as LLM-optimized format
|
|
1692
|
+
* const llmText = await client.data.exportJob("job_abc123", "llm");
|
|
1693
|
+
*
|
|
1694
|
+
* // Export as CSV
|
|
1695
|
+
* const csv = await client.data.exportJob("job_abc123", "csv");
|
|
1696
|
+
* ```
|
|
1697
|
+
*/
|
|
1698
|
+
async exportJob(jobId, format = "json") {
|
|
1699
|
+
if (!jobId || !jobId.trim()) {
|
|
1700
|
+
throw new Error("jobId is required and cannot be empty");
|
|
1701
|
+
}
|
|
1702
|
+
const result = await get(
|
|
1703
|
+
this.ctx,
|
|
1704
|
+
`/v1/data/jobs/${jobId}/export`,
|
|
1705
|
+
{ format }
|
|
1706
|
+
);
|
|
1707
|
+
return result.data;
|
|
1708
|
+
}
|
|
1640
1709
|
// ============================================
|
|
1641
1710
|
// DEALS
|
|
1642
1711
|
// ============================================
|
|
@@ -3013,6 +3082,31 @@ var StatusResource = class {
|
|
|
3013
3082
|
);
|
|
3014
3083
|
return result.data;
|
|
3015
3084
|
}
|
|
3085
|
+
/**
|
|
3086
|
+
* Get errors from a job
|
|
3087
|
+
* Useful for debugging large crawls without loading full results
|
|
3088
|
+
*
|
|
3089
|
+
* @example
|
|
3090
|
+
* ```ts
|
|
3091
|
+
* const errors = await client.status.getJobErrors("job_abc123", {
|
|
3092
|
+
* limit: 50,
|
|
3093
|
+
* offset: 0
|
|
3094
|
+
* });
|
|
3095
|
+
* console.log(errors.data);
|
|
3096
|
+
* console.log(errors.pagination.total);
|
|
3097
|
+
* ```
|
|
3098
|
+
*/
|
|
3099
|
+
async getJobErrors(jobId, options) {
|
|
3100
|
+
const result = await get(
|
|
3101
|
+
this.ctx,
|
|
3102
|
+
`/v1/status/${jobId}/errors`,
|
|
3103
|
+
{
|
|
3104
|
+
limit: options?.limit,
|
|
3105
|
+
offset: options?.offset
|
|
3106
|
+
}
|
|
3107
|
+
);
|
|
3108
|
+
return result.data;
|
|
3109
|
+
}
|
|
3016
3110
|
/**
|
|
3017
3111
|
* Cancel a pending or active job
|
|
3018
3112
|
*
|
|
@@ -3248,6 +3342,106 @@ var WebhooksResource = class {
|
|
|
3248
3342
|
const all = await this.list();
|
|
3249
3343
|
return all.data.filter((w) => w.event === event);
|
|
3250
3344
|
}
|
|
3345
|
+
/**
|
|
3346
|
+
* Rotate webhook secret
|
|
3347
|
+
* Rotates the secret while keeping the old one valid during grace period
|
|
3348
|
+
*
|
|
3349
|
+
* @example
|
|
3350
|
+
* ```ts
|
|
3351
|
+
* const result = await client.webhooks.rotateSecret("webhook_abc123", {
|
|
3352
|
+
* newSecret: "new-secure-secret-key",
|
|
3353
|
+
* gracePeriodHours: 24
|
|
3354
|
+
* });
|
|
3355
|
+
* console.log(result.secretVersion);
|
|
3356
|
+
* console.log(result.previousSecretValidUntil);
|
|
3357
|
+
* ```
|
|
3358
|
+
*/
|
|
3359
|
+
async rotateSecret(webhookId, options) {
|
|
3360
|
+
if (!webhookId || !webhookId.trim()) {
|
|
3361
|
+
throw new Error("webhookId is required and cannot be empty");
|
|
3362
|
+
}
|
|
3363
|
+
if (!options.newSecret || options.newSecret.length < 16) {
|
|
3364
|
+
throw new Error("newSecret must be at least 16 characters long");
|
|
3365
|
+
}
|
|
3366
|
+
const result = await post(
|
|
3367
|
+
this.ctx,
|
|
3368
|
+
`/v1/webhooks/${webhookId}/rotate`,
|
|
3369
|
+
{
|
|
3370
|
+
newSecret: options.newSecret,
|
|
3371
|
+
gracePeriodHours: options.gracePeriodHours ?? 24
|
|
3372
|
+
}
|
|
3373
|
+
);
|
|
3374
|
+
return result.data;
|
|
3375
|
+
}
|
|
3376
|
+
/**
|
|
3377
|
+
* Get webhook secret rotation status
|
|
3378
|
+
* Check current secret version and grace period status
|
|
3379
|
+
*
|
|
3380
|
+
* @example
|
|
3381
|
+
* ```ts
|
|
3382
|
+
* const status = await client.webhooks.getSecretStatus("webhook_abc123");
|
|
3383
|
+
* console.log(status.secretVersion);
|
|
3384
|
+
* if (status.gracePeriod?.active) {
|
|
3385
|
+
* console.log(`Grace period expires: ${status.gracePeriod.expiresAt}`);
|
|
3386
|
+
* }
|
|
3387
|
+
* ```
|
|
3388
|
+
*/
|
|
3389
|
+
async getSecretStatus(webhookId) {
|
|
3390
|
+
if (!webhookId || !webhookId.trim()) {
|
|
3391
|
+
throw new Error("webhookId is required and cannot be empty");
|
|
3392
|
+
}
|
|
3393
|
+
const result = await get(
|
|
3394
|
+
this.ctx,
|
|
3395
|
+
`/v1/webhooks/${webhookId}/secret-status`
|
|
3396
|
+
);
|
|
3397
|
+
return result.data;
|
|
3398
|
+
}
|
|
3399
|
+
/**
|
|
3400
|
+
* Verify webhook signature and replay protection
|
|
3401
|
+
* Validates signature, timestamp, and nonce from received webhook
|
|
3402
|
+
*
|
|
3403
|
+
* @example
|
|
3404
|
+
* ```ts
|
|
3405
|
+
* const isValid = await client.webhooks.verifySignature({
|
|
3406
|
+
* webhookId: "webhook_abc123",
|
|
3407
|
+
* payload: receivedPayload,
|
|
3408
|
+
* signature: headers["x-dealcrawl-signature"],
|
|
3409
|
+
* timestamp: parseInt(headers["x-dealcrawl-timestamp"]),
|
|
3410
|
+
* nonce: headers["x-dealcrawl-nonce"]
|
|
3411
|
+
* });
|
|
3412
|
+
* if (isValid.valid) {
|
|
3413
|
+
* console.log("Webhook is valid");
|
|
3414
|
+
* } else {
|
|
3415
|
+
* console.log(`Invalid: ${isValid.error}`);
|
|
3416
|
+
* }
|
|
3417
|
+
* ```
|
|
3418
|
+
*/
|
|
3419
|
+
async verifySignature(options) {
|
|
3420
|
+
if (!options.webhookId || !options.webhookId.trim()) {
|
|
3421
|
+
throw new Error("webhookId is required and cannot be empty");
|
|
3422
|
+
}
|
|
3423
|
+
if (!options.signature) {
|
|
3424
|
+
throw new Error("signature is required");
|
|
3425
|
+
}
|
|
3426
|
+
if (!options.timestamp || options.timestamp <= 0) {
|
|
3427
|
+
throw new Error("timestamp is required and must be positive");
|
|
3428
|
+
}
|
|
3429
|
+
if (!options.nonce || !/^[0-9a-f]{32}$/i.test(options.nonce)) {
|
|
3430
|
+
throw new Error("nonce must be a 32-character hex string");
|
|
3431
|
+
}
|
|
3432
|
+
const result = await post(
|
|
3433
|
+
this.ctx,
|
|
3434
|
+
"/v1/webhooks/verify",
|
|
3435
|
+
{
|
|
3436
|
+
webhookId: options.webhookId,
|
|
3437
|
+
payload: options.payload,
|
|
3438
|
+
signature: options.signature,
|
|
3439
|
+
timestamp: options.timestamp,
|
|
3440
|
+
nonce: options.nonce
|
|
3441
|
+
}
|
|
3442
|
+
);
|
|
3443
|
+
return result.data;
|
|
3444
|
+
}
|
|
3251
3445
|
};
|
|
3252
3446
|
|
|
3253
3447
|
// src/client.ts
|