@dealcrawl/sdk 2.0.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 +540 -0
- package/dist/sdk/src/client.d.ts +285 -0
- package/dist/sdk/src/client.d.ts.map +1 -0
- package/dist/sdk/src/client.js +336 -0
- package/dist/sdk/src/client.js.map +1 -0
- package/dist/sdk/src/error.d.ts +54 -0
- package/dist/sdk/src/error.d.ts.map +1 -0
- package/dist/sdk/src/error.js +115 -0
- package/dist/sdk/src/error.js.map +1 -0
- package/dist/sdk/src/index.d.ts +58 -0
- package/dist/sdk/src/index.d.ts.map +1 -0
- package/dist/sdk/src/index.js +65 -0
- package/dist/sdk/src/index.js.map +1 -0
- package/dist/sdk/src/resources/account.d.ts +143 -0
- package/dist/sdk/src/resources/account.d.ts.map +1 -0
- package/dist/sdk/src/resources/account.js +186 -0
- package/dist/sdk/src/resources/account.js.map +1 -0
- package/dist/sdk/src/resources/crawl.d.ts +87 -0
- package/dist/sdk/src/resources/crawl.d.ts.map +1 -0
- package/dist/sdk/src/resources/crawl.js +205 -0
- package/dist/sdk/src/resources/crawl.js.map +1 -0
- package/dist/sdk/src/resources/data.d.ts +157 -0
- package/dist/sdk/src/resources/data.d.ts.map +1 -0
- package/dist/sdk/src/resources/data.js +239 -0
- package/dist/sdk/src/resources/data.js.map +1 -0
- package/dist/sdk/src/resources/dork.d.ts +104 -0
- package/dist/sdk/src/resources/dork.d.ts.map +1 -0
- package/dist/sdk/src/resources/dork.js +163 -0
- package/dist/sdk/src/resources/dork.js.map +1 -0
- package/dist/sdk/src/resources/extract.d.ts +105 -0
- package/dist/sdk/src/resources/extract.d.ts.map +1 -0
- package/dist/sdk/src/resources/extract.js +246 -0
- package/dist/sdk/src/resources/extract.js.map +1 -0
- package/dist/sdk/src/resources/index.d.ts +14 -0
- package/dist/sdk/src/resources/index.d.ts.map +1 -0
- package/dist/sdk/src/resources/index.js +14 -0
- package/dist/sdk/src/resources/index.js.map +1 -0
- package/dist/sdk/src/resources/keys.d.ts +124 -0
- package/dist/sdk/src/resources/keys.d.ts.map +1 -0
- package/dist/sdk/src/resources/keys.js +168 -0
- package/dist/sdk/src/resources/keys.js.map +1 -0
- package/dist/sdk/src/resources/scrape.d.ts +53 -0
- package/dist/sdk/src/resources/scrape.d.ts.map +1 -0
- package/dist/sdk/src/resources/scrape.js +85 -0
- package/dist/sdk/src/resources/scrape.js.map +1 -0
- package/dist/sdk/src/resources/status.d.ts +100 -0
- package/dist/sdk/src/resources/status.d.ts.map +1 -0
- package/dist/sdk/src/resources/status.js +133 -0
- package/dist/sdk/src/resources/status.js.map +1 -0
- package/dist/sdk/src/resources/webhooks.d.ts +126 -0
- package/dist/sdk/src/resources/webhooks.d.ts.map +1 -0
- package/dist/sdk/src/resources/webhooks.js +167 -0
- package/dist/sdk/src/resources/webhooks.js.map +1 -0
- package/dist/sdk/src/types/config.d.ts +45 -0
- package/dist/sdk/src/types/config.d.ts.map +1 -0
- package/dist/sdk/src/types/config.js +10 -0
- package/dist/sdk/src/types/config.js.map +1 -0
- package/dist/sdk/src/types/index.d.ts +8 -0
- package/dist/sdk/src/types/index.d.ts.map +1 -0
- package/dist/sdk/src/types/index.js +8 -0
- package/dist/sdk/src/types/index.js.map +1 -0
- package/dist/sdk/src/types/options.d.ts +286 -0
- package/dist/sdk/src/types/options.d.ts.map +1 -0
- package/dist/sdk/src/types/options.js +6 -0
- package/dist/sdk/src/types/options.js.map +1 -0
- package/dist/sdk/src/types/responses.d.ts +385 -0
- package/dist/sdk/src/types/responses.d.ts.map +1 -0
- package/dist/sdk/src/types/responses.js +6 -0
- package/dist/sdk/src/types/responses.js.map +1 -0
- package/dist/sdk/src/utils/polling.d.ts +57 -0
- package/dist/sdk/src/utils/polling.d.ts.map +1 -0
- package/dist/sdk/src/utils/polling.js +110 -0
- package/dist/sdk/src/utils/polling.js.map +1 -0
- package/dist/sdk/src/utils/request.d.ts +47 -0
- package/dist/sdk/src/utils/request.d.ts.map +1 -0
- package/dist/sdk/src/utils/request.js +161 -0
- package/dist/sdk/src/utils/request.js.map +1 -0
- package/dist/shared/src/constants/errors.d.ts +26 -0
- package/dist/shared/src/constants/errors.d.ts.map +1 -0
- package/dist/shared/src/constants/errors.js +39 -0
- package/dist/shared/src/constants/errors.js.map +1 -0
- package/dist/shared/src/constants/http.d.ts +26 -0
- package/dist/shared/src/constants/http.d.ts.map +1 -0
- package/dist/shared/src/constants/http.js +26 -0
- package/dist/shared/src/constants/http.js.map +1 -0
- package/dist/shared/src/constants/index.d.ts +4 -0
- package/dist/shared/src/constants/index.d.ts.map +1 -0
- package/dist/shared/src/constants/index.js +5 -0
- package/dist/shared/src/constants/index.js.map +1 -0
- package/dist/shared/src/constants/limits.d.ts +52 -0
- package/dist/shared/src/constants/limits.d.ts.map +1 -0
- package/dist/shared/src/constants/limits.js +43 -0
- package/dist/shared/src/constants/limits.js.map +1 -0
- package/dist/shared/src/index.d.ts +5 -0
- package/dist/shared/src/index.d.ts.map +1 -0
- package/dist/shared/src/index.js +11 -0
- package/dist/shared/src/index.js.map +1 -0
- package/dist/shared/src/lib/index.d.ts +2 -0
- package/dist/shared/src/lib/index.d.ts.map +1 -0
- package/dist/shared/src/lib/index.js +2 -0
- package/dist/shared/src/lib/index.js.map +1 -0
- package/dist/shared/src/lib/redis.d.ts +14 -0
- package/dist/shared/src/lib/redis.d.ts.map +1 -0
- package/dist/shared/src/lib/redis.js +60 -0
- package/dist/shared/src/lib/redis.js.map +1 -0
- package/dist/shared/src/types/api-key.types.d.ts +94 -0
- package/dist/shared/src/types/api-key.types.d.ts.map +1 -0
- package/dist/shared/src/types/api-key.types.js +30 -0
- package/dist/shared/src/types/api-key.types.js.map +1 -0
- package/dist/shared/src/types/api.types.d.ts +38 -0
- package/dist/shared/src/types/api.types.d.ts.map +1 -0
- package/dist/shared/src/types/api.types.js +2 -0
- package/dist/shared/src/types/api.types.js.map +1 -0
- package/dist/shared/src/types/client.types.d.ts +73 -0
- package/dist/shared/src/types/client.types.d.ts.map +1 -0
- package/dist/shared/src/types/client.types.js +9 -0
- package/dist/shared/src/types/client.types.js.map +1 -0
- package/dist/shared/src/types/crawl.types.d.ts +65 -0
- package/dist/shared/src/types/crawl.types.d.ts.map +1 -0
- package/dist/shared/src/types/crawl.types.js +2 -0
- package/dist/shared/src/types/crawl.types.js.map +1 -0
- package/dist/shared/src/types/deal.types.d.ts +210 -0
- package/dist/shared/src/types/deal.types.d.ts.map +1 -0
- package/dist/shared/src/types/deal.types.js +6 -0
- package/dist/shared/src/types/deal.types.js.map +1 -0
- package/dist/shared/src/types/dork.types.d.ts +29 -0
- package/dist/shared/src/types/dork.types.d.ts.map +1 -0
- package/dist/shared/src/types/dork.types.js +2 -0
- package/dist/shared/src/types/dork.types.js.map +1 -0
- package/dist/shared/src/types/index.d.ts +8 -0
- package/dist/shared/src/types/index.d.ts.map +1 -0
- package/dist/shared/src/types/index.js +9 -0
- package/dist/shared/src/types/index.js.map +1 -0
- package/dist/shared/src/types/scrape.types.d.ts +151 -0
- package/dist/shared/src/types/scrape.types.d.ts.map +1 -0
- package/dist/shared/src/types/scrape.types.js +2 -0
- package/dist/shared/src/types/scrape.types.js.map +1 -0
- package/dist/shared/src/utils/date.d.ts +7 -0
- package/dist/shared/src/utils/date.d.ts.map +1 -0
- package/dist/shared/src/utils/date.js +25 -0
- package/dist/shared/src/utils/date.js.map +1 -0
- package/dist/shared/src/utils/hash.d.ts +4 -0
- package/dist/shared/src/utils/hash.d.ts.map +1 -0
- package/dist/shared/src/utils/hash.js +21 -0
- package/dist/shared/src/utils/hash.js.map +1 -0
- package/dist/shared/src/utils/index.d.ts +7 -0
- package/dist/shared/src/utils/index.d.ts.map +1 -0
- package/dist/shared/src/utils/index.js +8 -0
- package/dist/shared/src/utils/index.js.map +1 -0
- package/dist/shared/src/utils/logger.d.ts +66 -0
- package/dist/shared/src/utils/logger.d.ts.map +1 -0
- package/dist/shared/src/utils/logger.js +268 -0
- package/dist/shared/src/utils/logger.js.map +1 -0
- package/dist/shared/src/utils/retry.d.ts +11 -0
- package/dist/shared/src/utils/retry.d.ts.map +1 -0
- package/dist/shared/src/utils/retry.js +36 -0
- package/dist/shared/src/utils/retry.js.map +1 -0
- package/dist/shared/src/utils/url-validator.d.ts +37 -0
- package/dist/shared/src/utils/url-validator.d.ts.map +1 -0
- package/dist/shared/src/utils/url-validator.js +179 -0
- package/dist/shared/src/utils/url-validator.js.map +1 -0
- package/dist/shared/src/utils/url.d.ts +6 -0
- package/dist/shared/src/utils/url.d.ts.map +1 -0
- package/dist/shared/src/utils/url.js +56 -0
- package/dist/shared/src/utils/url.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
# @dealcrawl/sdk
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for the DealCrawl web scraping and crawling API.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@dealcrawl/sdk)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🚀 **Full API Coverage** - Access all 41 DealCrawl API endpoints
|
|
12
|
+
- 📦 **Zero Dependencies** - Uses native `fetch`, works everywhere
|
|
13
|
+
- 🔒 **Type-Safe** - Complete TypeScript definitions
|
|
14
|
+
- ⚡ **Automatic Retries** - Built-in retry logic with exponential backoff
|
|
15
|
+
- 🔄 **Polling Helpers** - `waitForResult()` for async job completion
|
|
16
|
+
- 🎯 **Resource Pattern** - Stripe/Twilio-style API design
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# npm
|
|
22
|
+
npm install @dealcrawl/sdk
|
|
23
|
+
|
|
24
|
+
# bun
|
|
25
|
+
bun add @dealcrawl/sdk
|
|
26
|
+
|
|
27
|
+
# pnpm
|
|
28
|
+
pnpm add @dealcrawl/sdk
|
|
29
|
+
|
|
30
|
+
# yarn
|
|
31
|
+
yarn add @dealcrawl/sdk
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { DealCrawl } from "@dealcrawl/sdk";
|
|
38
|
+
|
|
39
|
+
const client = new DealCrawl({
|
|
40
|
+
apiKey: process.env.DEALCRAWL_API_KEY!,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Scrape a single page with deal extraction
|
|
44
|
+
const job = await client.scrape.create({
|
|
45
|
+
url: "https://shop.example.com/product",
|
|
46
|
+
extractDeal: true,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Wait for result with automatic polling
|
|
50
|
+
const result = await client.waitForResult(job.jobId);
|
|
51
|
+
console.log(result);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
const client = new DealCrawl({
|
|
58
|
+
apiKey: "sk_xxx", // Required
|
|
59
|
+
baseUrl: "https://api.dealcrawl.dev", // Optional (default)
|
|
60
|
+
timeout: 30000, // Request timeout in ms
|
|
61
|
+
maxRetries: 3, // Retry attempts
|
|
62
|
+
retryDelay: 1000, // Base retry delay in ms
|
|
63
|
+
onRateLimit: (info) => console.log(info), // Rate limit callback
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Resources
|
|
68
|
+
|
|
69
|
+
### Scrape - Single Page Scraping
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// Basic scrape
|
|
73
|
+
const job = await client.scrape.create({
|
|
74
|
+
url: "https://example.com",
|
|
75
|
+
detectSignals: true,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// With deal extraction
|
|
79
|
+
const job = await client.scrape.extractDeal("https://shop.example.com/sale");
|
|
80
|
+
|
|
81
|
+
// With screenshot
|
|
82
|
+
const job = await client.scrape.withScreenshot("https://example.com", {
|
|
83
|
+
format: "webp",
|
|
84
|
+
fullPage: true,
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Options:**
|
|
89
|
+
| Option | Type | Default | Description |
|
|
90
|
+
|--------|------|---------|-------------|
|
|
91
|
+
| `url` | string | required | URL to scrape |
|
|
92
|
+
| `detectSignals` | boolean | true | Detect prices, discounts, urgency |
|
|
93
|
+
| `extractDeal` | boolean | false | Extract deal information |
|
|
94
|
+
| `extractWithAI` | boolean | false | Use AI for extraction |
|
|
95
|
+
| `useAdvancedModel` | boolean | false | Use GPT-4o (higher cost) |
|
|
96
|
+
| `minDealScore` | number | 0 | Minimum deal score (0-100) |
|
|
97
|
+
| `screenshot` | object | - | Screenshot options |
|
|
98
|
+
| `excludeTags` | string[] | - | HTML tags to exclude |
|
|
99
|
+
| `onlyMainContent` | boolean | true | Extract main content only |
|
|
100
|
+
|
|
101
|
+
### Crawl - Website Crawling
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Basic crawl
|
|
105
|
+
const job = await client.crawl.create({
|
|
106
|
+
url: "https://shop.example.com",
|
|
107
|
+
maxDepth: 3,
|
|
108
|
+
maxPages: 100,
|
|
109
|
+
extractDeal: true,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Using templates
|
|
113
|
+
const job = await client.crawl.withTemplate("ecommerce", {
|
|
114
|
+
url: "https://shop.example.com",
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Analyze before crawling
|
|
118
|
+
const analysis = await client.crawl.analyze("https://shop.example.com");
|
|
119
|
+
console.log(analysis.recommendedTemplate);
|
|
120
|
+
console.log(analysis.estimatedPages);
|
|
121
|
+
|
|
122
|
+
// Find deals (convenience method)
|
|
123
|
+
const job = await client.crawl.forDeals("https://shop.example.com", {
|
|
124
|
+
minDealScore: 70,
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Available Templates:**
|
|
129
|
+
|
|
130
|
+
- `ecommerce` - Product pages and online stores
|
|
131
|
+
- `marketplace` - Multi-vendor marketplaces
|
|
132
|
+
- `blog` - Blog posts and articles
|
|
133
|
+
- `docs` - Documentation sites
|
|
134
|
+
- `custom` - No preset, use your own settings
|
|
135
|
+
|
|
136
|
+
### Extract - LLM-Based Extraction
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// Schema-based extraction
|
|
140
|
+
const job = await client.extract.withSchema("https://example.com/product", {
|
|
141
|
+
type: "object",
|
|
142
|
+
properties: {
|
|
143
|
+
name: { type: "string" },
|
|
144
|
+
price: { type: "number" },
|
|
145
|
+
features: { type: "array", items: { type: "string" } },
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Prompt-based extraction
|
|
150
|
+
const job = await client.extract.withPrompt(
|
|
151
|
+
"https://example.com/article",
|
|
152
|
+
"Extract the article title, author, and main points"
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// Pre-built extractors
|
|
156
|
+
const job = await client.extract.product("https://shop.example.com/item");
|
|
157
|
+
const job = await client.extract.article("https://blog.example.com/post");
|
|
158
|
+
const job = await client.extract.contact("https://example.com/contact");
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Dork - Google Dork Searches
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// Basic dork search
|
|
165
|
+
const job = await client.dork.create({
|
|
166
|
+
query: "discount coupon",
|
|
167
|
+
site: "amazon.com",
|
|
168
|
+
maxResults: 50,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Find deals on a site
|
|
172
|
+
const job = await client.dork.findDeals("amazon.com");
|
|
173
|
+
|
|
174
|
+
// Find products
|
|
175
|
+
const job = await client.dork.findProducts("shop.example.com");
|
|
176
|
+
|
|
177
|
+
// Find PDFs
|
|
178
|
+
const job = await client.dork.findPDFs("docs.example.com", "user guide");
|
|
179
|
+
|
|
180
|
+
// Build query string (for preview)
|
|
181
|
+
const query = client.dork.buildQuery({
|
|
182
|
+
query: "laptop deals",
|
|
183
|
+
site: "amazon.com",
|
|
184
|
+
inTitle: "discount",
|
|
185
|
+
});
|
|
186
|
+
// Returns: "laptop deals site:amazon.com intitle:discount"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Status - Job Management
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
// Get job status
|
|
193
|
+
const status = await client.status.get(jobId);
|
|
194
|
+
|
|
195
|
+
// Get deals from a job
|
|
196
|
+
const deals = await client.status.getDeals(jobId, {
|
|
197
|
+
minScore: 70,
|
|
198
|
+
limit: 20,
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Resume a failed/paused job
|
|
202
|
+
const resumed = await client.status.resume(jobId);
|
|
203
|
+
|
|
204
|
+
// Get job metrics
|
|
205
|
+
const metrics = await client.status.getMetrics(jobId);
|
|
206
|
+
|
|
207
|
+
// Cancel a job
|
|
208
|
+
await client.status.cancel(jobId);
|
|
209
|
+
|
|
210
|
+
// Convenience methods
|
|
211
|
+
const isComplete = await client.status.isComplete(jobId);
|
|
212
|
+
const succeeded = await client.status.succeeded(jobId);
|
|
213
|
+
const result = await client.status.getResult(jobId);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Data - Jobs & Deals Access
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// List jobs with filtering
|
|
220
|
+
const jobs = await client.data.listJobs({
|
|
221
|
+
status: "completed",
|
|
222
|
+
type: "crawl",
|
|
223
|
+
page: 1,
|
|
224
|
+
limit: 20,
|
|
225
|
+
sortBy: "created_at",
|
|
226
|
+
sortOrder: "desc",
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// List deals with filtering
|
|
230
|
+
const deals = await client.data.listDeals({
|
|
231
|
+
minScore: 70,
|
|
232
|
+
category: "electronics",
|
|
233
|
+
sortBy: "deal_score",
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Get top deals
|
|
237
|
+
const topDeals = await client.data.getTopDeals(20, 80);
|
|
238
|
+
|
|
239
|
+
// Export data
|
|
240
|
+
const jsonExport = await client.data.exportDeals({ format: "json" });
|
|
241
|
+
const csvExport = await client.data.exportDeals({ format: "csv" });
|
|
242
|
+
|
|
243
|
+
// Get statistics
|
|
244
|
+
const stats = await client.data.getStats();
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Webhooks - Event Notifications
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// Create a webhook
|
|
251
|
+
const webhook = await client.webhooks.create({
|
|
252
|
+
event: "deal.found",
|
|
253
|
+
url: "https://my-server.com/webhooks/deals",
|
|
254
|
+
secret: "my-webhook-secret",
|
|
255
|
+
minDealScore: 70,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// List webhooks
|
|
259
|
+
const webhooks = await client.webhooks.list();
|
|
260
|
+
|
|
261
|
+
// Test a webhook
|
|
262
|
+
const result = await client.webhooks.test(webhookId);
|
|
263
|
+
|
|
264
|
+
// Enable/disable
|
|
265
|
+
await client.webhooks.enable(webhookId);
|
|
266
|
+
await client.webhooks.disable(webhookId);
|
|
267
|
+
|
|
268
|
+
// Delete
|
|
269
|
+
await client.webhooks.delete(webhookId);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Events:**
|
|
273
|
+
|
|
274
|
+
- `deal.found` - New deal discovered
|
|
275
|
+
- `deal.synced` - Deal synced to DealUp
|
|
276
|
+
- `crawl.completed` - Crawl job finished
|
|
277
|
+
- `crawl.failed` - Crawl job failed
|
|
278
|
+
|
|
279
|
+
### Keys - API Key Management
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
// List all keys
|
|
283
|
+
const keys = await client.keys.list();
|
|
284
|
+
|
|
285
|
+
// Create a new key
|
|
286
|
+
const newKey = await client.keys.create({
|
|
287
|
+
name: "Production Key",
|
|
288
|
+
scopes: ["scrape:write", "crawl:write", "data:read"],
|
|
289
|
+
expiresInDays: 365,
|
|
290
|
+
});
|
|
291
|
+
// ⚠️ Save newKey.key immediately - it won't be shown again!
|
|
292
|
+
|
|
293
|
+
// Rotate a key
|
|
294
|
+
const rotated = await client.keys.rotate(keyId, {
|
|
295
|
+
newName: "Production Key v2",
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Revoke a key
|
|
299
|
+
await client.keys.revoke(keyId);
|
|
300
|
+
|
|
301
|
+
// Get key stats
|
|
302
|
+
const stats = await client.keys.getStats(keyId, { days: 30 });
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Account - Profile & Preferences
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
// Get account info
|
|
309
|
+
const account = await client.account.get();
|
|
310
|
+
console.log(account.tier); // "free" | "pro" | "enterprise"
|
|
311
|
+
console.log(account.usage);
|
|
312
|
+
|
|
313
|
+
// Get metrics
|
|
314
|
+
const metrics = await client.account.getMetrics();
|
|
315
|
+
|
|
316
|
+
// Get recommendations
|
|
317
|
+
const recommendations = await client.account.getRecommendations();
|
|
318
|
+
|
|
319
|
+
// Update preferences
|
|
320
|
+
await client.account.updatePreferences({
|
|
321
|
+
minDealScore: 70,
|
|
322
|
+
autoSync: true,
|
|
323
|
+
preferredCategories: ["software", "courses"],
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// Convenience methods
|
|
327
|
+
const remaining = await client.account.getRemainingQuota("scrapes");
|
|
328
|
+
const hasQuota = await client.account.hasQuota("crawls", 5);
|
|
329
|
+
const isPremium = await client.account.isPremium();
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Polling & Waiting
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
// Wait for a single job
|
|
336
|
+
const result = await client.waitForResult(jobId, {
|
|
337
|
+
pollInterval: 2000, // Check every 2 seconds
|
|
338
|
+
timeout: 300000, // 5 minute timeout
|
|
339
|
+
onProgress: (status) => console.log(`Progress: ${status.progress}%`),
|
|
340
|
+
onStatusChange: (newStatus, oldStatus) => {
|
|
341
|
+
console.log(`Status changed: ${oldStatus} → ${newStatus}`);
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// Wait for multiple jobs
|
|
346
|
+
const results = await client.waitForAll([jobId1, jobId2, jobId3]);
|
|
347
|
+
|
|
348
|
+
// Wait for any job to complete
|
|
349
|
+
const firstResult = await client.waitForAny([jobId1, jobId2, jobId3]);
|
|
350
|
+
|
|
351
|
+
// Convenience: scrape and wait
|
|
352
|
+
const result = await client.scrapeAndWait({
|
|
353
|
+
url: "https://example.com",
|
|
354
|
+
extractDeal: true,
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
// Convenience: crawl and wait
|
|
358
|
+
const result = await client.crawlAndWait({
|
|
359
|
+
url: "https://shop.example.com",
|
|
360
|
+
maxPages: 50,
|
|
361
|
+
});
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Error Handling
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { DealCrawl, DealCrawlError, ERROR_CODES } from "@dealcrawl/sdk";
|
|
368
|
+
|
|
369
|
+
try {
|
|
370
|
+
const result = await client.scrape.create({ url: "..." });
|
|
371
|
+
} catch (error) {
|
|
372
|
+
if (error instanceof DealCrawlError) {
|
|
373
|
+
console.log(error.code); // e.g., "RATE_LIMIT_EXCEEDED"
|
|
374
|
+
console.log(error.statusCode); // HTTP status code
|
|
375
|
+
console.log(error.message); // Human-readable message
|
|
376
|
+
console.log(error.details); // Additional details
|
|
377
|
+
|
|
378
|
+
// Check error type
|
|
379
|
+
if (error.isRateLimited()) {
|
|
380
|
+
console.log(`Retry after ${error.retryAfter} seconds`);
|
|
381
|
+
}
|
|
382
|
+
if (error.isAuthError()) {
|
|
383
|
+
console.log("Check your API key");
|
|
384
|
+
}
|
|
385
|
+
if (error.isRetryable()) {
|
|
386
|
+
// Automatic retry was attempted
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Error Codes:**
|
|
393
|
+
|
|
394
|
+
- `INVALID_API_KEY` - API key is invalid or missing
|
|
395
|
+
- `RATE_LIMIT_EXCEEDED` - Too many requests
|
|
396
|
+
- `QUOTA_EXCEEDED` - Monthly quota exceeded
|
|
397
|
+
- `JOB_NOT_FOUND` - Job ID doesn't exist
|
|
398
|
+
- `JOB_TIMEOUT` - Job didn't complete in time
|
|
399
|
+
- `FETCH_FAILED` - Network request failed
|
|
400
|
+
|
|
401
|
+
## TypeScript Types
|
|
402
|
+
|
|
403
|
+
All types are exported for your convenience:
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
import type {
|
|
407
|
+
// Configuration
|
|
408
|
+
DealCrawlConfig,
|
|
409
|
+
|
|
410
|
+
// Request Options
|
|
411
|
+
ScrapeOptions,
|
|
412
|
+
CrawlOptions,
|
|
413
|
+
ExtractOptions,
|
|
414
|
+
DorkOptions,
|
|
415
|
+
|
|
416
|
+
// Responses
|
|
417
|
+
JobStatusResponse,
|
|
418
|
+
ListDealsResponse,
|
|
419
|
+
DealItem,
|
|
420
|
+
|
|
421
|
+
// Re-exports from @dealcrawl/shared
|
|
422
|
+
ScrapeResult,
|
|
423
|
+
CrawlResult,
|
|
424
|
+
ExtractedDeal,
|
|
425
|
+
Signal,
|
|
426
|
+
} from "@dealcrawl/sdk";
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Examples
|
|
430
|
+
|
|
431
|
+
### Find Best Deals on a Site
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
async function findBestDeals(siteUrl: string) {
|
|
435
|
+
const client = new DealCrawl({ apiKey: process.env.DEALCRAWL_API_KEY! });
|
|
436
|
+
|
|
437
|
+
// Crawl the site for deals
|
|
438
|
+
const job = await client.crawl.forDeals(siteUrl, {
|
|
439
|
+
maxPages: 200,
|
|
440
|
+
minDealScore: 60,
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// Wait for completion
|
|
444
|
+
const result = await client.waitForResult(job.jobId, {
|
|
445
|
+
timeout: 600000, // 10 minutes
|
|
446
|
+
onProgress: (s) => console.log(`Crawled: ${s.progress}%`),
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
if (result.status === "failed") {
|
|
450
|
+
throw new Error(result.error);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Get the best deals
|
|
454
|
+
const deals = await client.status.getDeals(job.jobId, {
|
|
455
|
+
minScore: 80,
|
|
456
|
+
limit: 50,
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
return deals.deals.sort((a, b) => b.dealScore - a.dealScore);
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Extract Product Information
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
async function extractProduct(productUrl: string) {
|
|
467
|
+
const client = new DealCrawl({ apiKey: process.env.DEALCRAWL_API_KEY! });
|
|
468
|
+
|
|
469
|
+
const result = await client.extractAndWait({
|
|
470
|
+
url: productUrl,
|
|
471
|
+
schema: {
|
|
472
|
+
type: "object",
|
|
473
|
+
properties: {
|
|
474
|
+
name: { type: "string" },
|
|
475
|
+
price: { type: "number" },
|
|
476
|
+
originalPrice: { type: "number" },
|
|
477
|
+
discount: { type: "string" },
|
|
478
|
+
rating: { type: "number" },
|
|
479
|
+
reviews: { type: "number" },
|
|
480
|
+
availability: { type: "string" },
|
|
481
|
+
features: { type: "array", items: { type: "string" } },
|
|
482
|
+
},
|
|
483
|
+
required: ["name", "price"],
|
|
484
|
+
},
|
|
485
|
+
model: "gpt-4o-mini",
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
return result.result;
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### Monitor for New Deals
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
async function setupDealMonitoring(webhookUrl: string) {
|
|
496
|
+
const client = new DealCrawl({ apiKey: process.env.DEALCRAWL_API_KEY! });
|
|
497
|
+
|
|
498
|
+
// Create webhook for high-score deals
|
|
499
|
+
await client.webhooks.create({
|
|
500
|
+
event: "deal.found",
|
|
501
|
+
url: webhookUrl,
|
|
502
|
+
minDealScore: 85,
|
|
503
|
+
categories: ["software", "courses"],
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// Set up preferences
|
|
507
|
+
await client.account.updatePreferences({
|
|
508
|
+
minDealScore: 70,
|
|
509
|
+
webhookEnabled: true,
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
console.log("Deal monitoring configured!");
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
## Browser Usage
|
|
517
|
+
|
|
518
|
+
The SDK works in browsers with native `fetch` support:
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
// In a browser environment
|
|
522
|
+
import { DealCrawl } from "@dealcrawl/sdk";
|
|
523
|
+
|
|
524
|
+
const client = new DealCrawl({
|
|
525
|
+
apiKey: "your-api-key", // ⚠️ Don't expose keys in client-side code!
|
|
526
|
+
});
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
> **Warning:** Never expose your API key in client-side code. Use a backend proxy or edge function.
|
|
530
|
+
|
|
531
|
+
## Compatibility
|
|
532
|
+
|
|
533
|
+
- **Node.js**: 18.0+
|
|
534
|
+
- **Bun**: All versions
|
|
535
|
+
- **Browser**: Modern browsers with `fetch` support
|
|
536
|
+
- **TypeScript**: 5.0+
|
|
537
|
+
|
|
538
|
+
## License
|
|
539
|
+
|
|
540
|
+
MIT © [DealUp](https://dealup.cc)
|