@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.
Files changed (166) hide show
  1. package/README.md +540 -0
  2. package/dist/sdk/src/client.d.ts +285 -0
  3. package/dist/sdk/src/client.d.ts.map +1 -0
  4. package/dist/sdk/src/client.js +336 -0
  5. package/dist/sdk/src/client.js.map +1 -0
  6. package/dist/sdk/src/error.d.ts +54 -0
  7. package/dist/sdk/src/error.d.ts.map +1 -0
  8. package/dist/sdk/src/error.js +115 -0
  9. package/dist/sdk/src/error.js.map +1 -0
  10. package/dist/sdk/src/index.d.ts +58 -0
  11. package/dist/sdk/src/index.d.ts.map +1 -0
  12. package/dist/sdk/src/index.js +65 -0
  13. package/dist/sdk/src/index.js.map +1 -0
  14. package/dist/sdk/src/resources/account.d.ts +143 -0
  15. package/dist/sdk/src/resources/account.d.ts.map +1 -0
  16. package/dist/sdk/src/resources/account.js +186 -0
  17. package/dist/sdk/src/resources/account.js.map +1 -0
  18. package/dist/sdk/src/resources/crawl.d.ts +87 -0
  19. package/dist/sdk/src/resources/crawl.d.ts.map +1 -0
  20. package/dist/sdk/src/resources/crawl.js +205 -0
  21. package/dist/sdk/src/resources/crawl.js.map +1 -0
  22. package/dist/sdk/src/resources/data.d.ts +157 -0
  23. package/dist/sdk/src/resources/data.d.ts.map +1 -0
  24. package/dist/sdk/src/resources/data.js +239 -0
  25. package/dist/sdk/src/resources/data.js.map +1 -0
  26. package/dist/sdk/src/resources/dork.d.ts +104 -0
  27. package/dist/sdk/src/resources/dork.d.ts.map +1 -0
  28. package/dist/sdk/src/resources/dork.js +163 -0
  29. package/dist/sdk/src/resources/dork.js.map +1 -0
  30. package/dist/sdk/src/resources/extract.d.ts +105 -0
  31. package/dist/sdk/src/resources/extract.d.ts.map +1 -0
  32. package/dist/sdk/src/resources/extract.js +246 -0
  33. package/dist/sdk/src/resources/extract.js.map +1 -0
  34. package/dist/sdk/src/resources/index.d.ts +14 -0
  35. package/dist/sdk/src/resources/index.d.ts.map +1 -0
  36. package/dist/sdk/src/resources/index.js +14 -0
  37. package/dist/sdk/src/resources/index.js.map +1 -0
  38. package/dist/sdk/src/resources/keys.d.ts +124 -0
  39. package/dist/sdk/src/resources/keys.d.ts.map +1 -0
  40. package/dist/sdk/src/resources/keys.js +168 -0
  41. package/dist/sdk/src/resources/keys.js.map +1 -0
  42. package/dist/sdk/src/resources/scrape.d.ts +53 -0
  43. package/dist/sdk/src/resources/scrape.d.ts.map +1 -0
  44. package/dist/sdk/src/resources/scrape.js +85 -0
  45. package/dist/sdk/src/resources/scrape.js.map +1 -0
  46. package/dist/sdk/src/resources/status.d.ts +100 -0
  47. package/dist/sdk/src/resources/status.d.ts.map +1 -0
  48. package/dist/sdk/src/resources/status.js +133 -0
  49. package/dist/sdk/src/resources/status.js.map +1 -0
  50. package/dist/sdk/src/resources/webhooks.d.ts +126 -0
  51. package/dist/sdk/src/resources/webhooks.d.ts.map +1 -0
  52. package/dist/sdk/src/resources/webhooks.js +167 -0
  53. package/dist/sdk/src/resources/webhooks.js.map +1 -0
  54. package/dist/sdk/src/types/config.d.ts +45 -0
  55. package/dist/sdk/src/types/config.d.ts.map +1 -0
  56. package/dist/sdk/src/types/config.js +10 -0
  57. package/dist/sdk/src/types/config.js.map +1 -0
  58. package/dist/sdk/src/types/index.d.ts +8 -0
  59. package/dist/sdk/src/types/index.d.ts.map +1 -0
  60. package/dist/sdk/src/types/index.js +8 -0
  61. package/dist/sdk/src/types/index.js.map +1 -0
  62. package/dist/sdk/src/types/options.d.ts +286 -0
  63. package/dist/sdk/src/types/options.d.ts.map +1 -0
  64. package/dist/sdk/src/types/options.js +6 -0
  65. package/dist/sdk/src/types/options.js.map +1 -0
  66. package/dist/sdk/src/types/responses.d.ts +385 -0
  67. package/dist/sdk/src/types/responses.d.ts.map +1 -0
  68. package/dist/sdk/src/types/responses.js +6 -0
  69. package/dist/sdk/src/types/responses.js.map +1 -0
  70. package/dist/sdk/src/utils/polling.d.ts +57 -0
  71. package/dist/sdk/src/utils/polling.d.ts.map +1 -0
  72. package/dist/sdk/src/utils/polling.js +110 -0
  73. package/dist/sdk/src/utils/polling.js.map +1 -0
  74. package/dist/sdk/src/utils/request.d.ts +47 -0
  75. package/dist/sdk/src/utils/request.d.ts.map +1 -0
  76. package/dist/sdk/src/utils/request.js +161 -0
  77. package/dist/sdk/src/utils/request.js.map +1 -0
  78. package/dist/shared/src/constants/errors.d.ts +26 -0
  79. package/dist/shared/src/constants/errors.d.ts.map +1 -0
  80. package/dist/shared/src/constants/errors.js +39 -0
  81. package/dist/shared/src/constants/errors.js.map +1 -0
  82. package/dist/shared/src/constants/http.d.ts +26 -0
  83. package/dist/shared/src/constants/http.d.ts.map +1 -0
  84. package/dist/shared/src/constants/http.js +26 -0
  85. package/dist/shared/src/constants/http.js.map +1 -0
  86. package/dist/shared/src/constants/index.d.ts +4 -0
  87. package/dist/shared/src/constants/index.d.ts.map +1 -0
  88. package/dist/shared/src/constants/index.js +5 -0
  89. package/dist/shared/src/constants/index.js.map +1 -0
  90. package/dist/shared/src/constants/limits.d.ts +52 -0
  91. package/dist/shared/src/constants/limits.d.ts.map +1 -0
  92. package/dist/shared/src/constants/limits.js +43 -0
  93. package/dist/shared/src/constants/limits.js.map +1 -0
  94. package/dist/shared/src/index.d.ts +5 -0
  95. package/dist/shared/src/index.d.ts.map +1 -0
  96. package/dist/shared/src/index.js +11 -0
  97. package/dist/shared/src/index.js.map +1 -0
  98. package/dist/shared/src/lib/index.d.ts +2 -0
  99. package/dist/shared/src/lib/index.d.ts.map +1 -0
  100. package/dist/shared/src/lib/index.js +2 -0
  101. package/dist/shared/src/lib/index.js.map +1 -0
  102. package/dist/shared/src/lib/redis.d.ts +14 -0
  103. package/dist/shared/src/lib/redis.d.ts.map +1 -0
  104. package/dist/shared/src/lib/redis.js +60 -0
  105. package/dist/shared/src/lib/redis.js.map +1 -0
  106. package/dist/shared/src/types/api-key.types.d.ts +94 -0
  107. package/dist/shared/src/types/api-key.types.d.ts.map +1 -0
  108. package/dist/shared/src/types/api-key.types.js +30 -0
  109. package/dist/shared/src/types/api-key.types.js.map +1 -0
  110. package/dist/shared/src/types/api.types.d.ts +38 -0
  111. package/dist/shared/src/types/api.types.d.ts.map +1 -0
  112. package/dist/shared/src/types/api.types.js +2 -0
  113. package/dist/shared/src/types/api.types.js.map +1 -0
  114. package/dist/shared/src/types/client.types.d.ts +73 -0
  115. package/dist/shared/src/types/client.types.d.ts.map +1 -0
  116. package/dist/shared/src/types/client.types.js +9 -0
  117. package/dist/shared/src/types/client.types.js.map +1 -0
  118. package/dist/shared/src/types/crawl.types.d.ts +65 -0
  119. package/dist/shared/src/types/crawl.types.d.ts.map +1 -0
  120. package/dist/shared/src/types/crawl.types.js +2 -0
  121. package/dist/shared/src/types/crawl.types.js.map +1 -0
  122. package/dist/shared/src/types/deal.types.d.ts +210 -0
  123. package/dist/shared/src/types/deal.types.d.ts.map +1 -0
  124. package/dist/shared/src/types/deal.types.js +6 -0
  125. package/dist/shared/src/types/deal.types.js.map +1 -0
  126. package/dist/shared/src/types/dork.types.d.ts +29 -0
  127. package/dist/shared/src/types/dork.types.d.ts.map +1 -0
  128. package/dist/shared/src/types/dork.types.js +2 -0
  129. package/dist/shared/src/types/dork.types.js.map +1 -0
  130. package/dist/shared/src/types/index.d.ts +8 -0
  131. package/dist/shared/src/types/index.d.ts.map +1 -0
  132. package/dist/shared/src/types/index.js +9 -0
  133. package/dist/shared/src/types/index.js.map +1 -0
  134. package/dist/shared/src/types/scrape.types.d.ts +151 -0
  135. package/dist/shared/src/types/scrape.types.d.ts.map +1 -0
  136. package/dist/shared/src/types/scrape.types.js +2 -0
  137. package/dist/shared/src/types/scrape.types.js.map +1 -0
  138. package/dist/shared/src/utils/date.d.ts +7 -0
  139. package/dist/shared/src/utils/date.d.ts.map +1 -0
  140. package/dist/shared/src/utils/date.js +25 -0
  141. package/dist/shared/src/utils/date.js.map +1 -0
  142. package/dist/shared/src/utils/hash.d.ts +4 -0
  143. package/dist/shared/src/utils/hash.d.ts.map +1 -0
  144. package/dist/shared/src/utils/hash.js +21 -0
  145. package/dist/shared/src/utils/hash.js.map +1 -0
  146. package/dist/shared/src/utils/index.d.ts +7 -0
  147. package/dist/shared/src/utils/index.d.ts.map +1 -0
  148. package/dist/shared/src/utils/index.js +8 -0
  149. package/dist/shared/src/utils/index.js.map +1 -0
  150. package/dist/shared/src/utils/logger.d.ts +66 -0
  151. package/dist/shared/src/utils/logger.d.ts.map +1 -0
  152. package/dist/shared/src/utils/logger.js +268 -0
  153. package/dist/shared/src/utils/logger.js.map +1 -0
  154. package/dist/shared/src/utils/retry.d.ts +11 -0
  155. package/dist/shared/src/utils/retry.d.ts.map +1 -0
  156. package/dist/shared/src/utils/retry.js +36 -0
  157. package/dist/shared/src/utils/retry.js.map +1 -0
  158. package/dist/shared/src/utils/url-validator.d.ts +37 -0
  159. package/dist/shared/src/utils/url-validator.d.ts.map +1 -0
  160. package/dist/shared/src/utils/url-validator.js +179 -0
  161. package/dist/shared/src/utils/url-validator.js.map +1 -0
  162. package/dist/shared/src/utils/url.d.ts +6 -0
  163. package/dist/shared/src/utils/url.d.ts.map +1 -0
  164. package/dist/shared/src/utils/url.js +56 -0
  165. package/dist/shared/src/utils/url.js.map +1 -0
  166. 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
+ [![npm version](https://img.shields.io/npm/v/@dealcrawl/sdk.svg)](https://www.npmjs.com/package/@dealcrawl/sdk)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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)