@dealcrawl/sdk 2.5.0 → 2.6.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/dist/index.js CHANGED
@@ -12,33 +12,164 @@ var DEFAULT_CONFIG = {
12
12
 
13
13
  // src/error.ts
14
14
  var ERROR_CODES = {
15
- // Authentication
16
- INVALID_API_KEY: "INVALID_API_KEY",
17
- MISSING_API_KEY: "MISSING_API_KEY",
18
- API_KEY_EXPIRED: "API_KEY_EXPIRED",
19
- ACCOUNT_SUSPENDED: "ACCOUNT_SUSPENDED",
20
- // Rate limiting
15
+ // ============================================
16
+ // Authentication & Authorization (4xx)
17
+ // ============================================
18
+ /** Missing or invalid Authorization header */
19
+ AUTH_MISSING_HEADER: "AUTH_MISSING_HEADER",
20
+ /** The provided API key is invalid or expired */
21
+ AUTH_INVALID_API_KEY: "AUTH_INVALID_API_KEY",
22
+ /** Your API key has expired */
23
+ AUTH_API_KEY_EXPIRED: "AUTH_API_KEY_EXPIRED",
24
+ /** Your API key has been revoked */
25
+ AUTH_API_KEY_REVOKED: "AUTH_API_KEY_REVOKED",
26
+ /** API key does not have required permissions */
27
+ AUTH_INSUFFICIENT_SCOPE: "AUTH_INSUFFICIENT_SCOPE",
28
+ /** Your account has been suspended */
29
+ AUTH_ACCOUNT_SUSPENDED: "AUTH_ACCOUNT_SUSPENDED",
30
+ // Legacy aliases (for backward compatibility)
31
+ /** @deprecated Use AUTH_INVALID_API_KEY instead */
32
+ INVALID_API_KEY: "AUTH_INVALID_API_KEY",
33
+ /** @deprecated Use AUTH_MISSING_HEADER instead */
34
+ MISSING_API_KEY: "AUTH_MISSING_HEADER",
35
+ /** @deprecated Use AUTH_API_KEY_EXPIRED instead */
36
+ API_KEY_EXPIRED: "AUTH_API_KEY_EXPIRED",
37
+ /** @deprecated Use AUTH_ACCOUNT_SUSPENDED instead */
38
+ ACCOUNT_SUSPENDED: "AUTH_ACCOUNT_SUSPENDED",
39
+ // ============================================
40
+ // Rate Limiting (429)
41
+ // ============================================
42
+ /** Rate limit exceeded. Please try again later */
21
43
  RATE_LIMIT_EXCEEDED: "RATE_LIMIT_EXCEEDED",
22
- QUOTA_EXCEEDED: "QUOTA_EXCEEDED",
23
- // Validation
24
- INVALID_URL: "INVALID_URL",
25
- INVALID_REQUEST: "INVALID_REQUEST",
26
- MISSING_REQUIRED_FIELD: "MISSING_REQUIRED_FIELD",
27
- // Job errors
28
- JOB_NOT_FOUND: "JOB_NOT_FOUND",
29
- JOB_FAILED: "JOB_FAILED",
44
+ /** Monthly quota exceeded. Upgrade your plan for more */
45
+ RATE_QUOTA_EXCEEDED: "RATE_QUOTA_EXCEEDED",
46
+ /** Concurrent job limit reached */
47
+ RATE_CONCURRENT_LIMIT: "RATE_CONCURRENT_LIMIT",
48
+ // Legacy aliases
49
+ /** @deprecated Use RATE_QUOTA_EXCEEDED instead */
50
+ QUOTA_EXCEEDED: "RATE_QUOTA_EXCEEDED",
51
+ // ============================================
52
+ // Validation (400, 422)
53
+ // ============================================
54
+ /** The provided input is invalid */
55
+ VALID_INVALID_INPUT: "VALID_INVALID_INPUT",
56
+ /** Required field is missing */
57
+ VALID_MISSING_FIELD: "VALID_MISSING_FIELD",
58
+ /** The provided URL is not valid */
59
+ VALID_INVALID_URL: "VALID_INVALID_URL",
60
+ /** Invalid schema format */
61
+ VALID_INVALID_SCHEMA: "VALID_INVALID_SCHEMA",
62
+ /** Invalid format */
63
+ VALID_INVALID_FORMAT: "VALID_INVALID_FORMAT",
64
+ // Legacy aliases
65
+ /** @deprecated Use VALID_INVALID_URL instead */
66
+ INVALID_URL: "VALID_INVALID_URL",
67
+ /** @deprecated Use VALID_INVALID_INPUT instead */
68
+ INVALID_REQUEST: "VALID_INVALID_INPUT",
69
+ /** @deprecated Use VALID_MISSING_FIELD instead */
70
+ MISSING_REQUIRED_FIELD: "VALID_MISSING_FIELD",
71
+ // ============================================
72
+ // Resources (404)
73
+ // ============================================
74
+ /** The requested resource was not found */
75
+ RESOURCE_NOT_FOUND: "RESOURCE_NOT_FOUND",
76
+ /** Job not found */
77
+ RESOURCE_JOB_NOT_FOUND: "RESOURCE_JOB_NOT_FOUND",
78
+ /** Webhook not found */
79
+ RESOURCE_WEBHOOK_NOT_FOUND: "RESOURCE_WEBHOOK_NOT_FOUND",
80
+ /** API key not found */
81
+ RESOURCE_KEY_NOT_FOUND: "RESOURCE_KEY_NOT_FOUND",
82
+ // Legacy aliases
83
+ /** @deprecated Use RESOURCE_JOB_NOT_FOUND instead */
84
+ JOB_NOT_FOUND: "RESOURCE_JOB_NOT_FOUND",
85
+ // ============================================
86
+ // Job Processing (422, 503)
87
+ // ============================================
88
+ /** Failed to create job */
89
+ JOB_CREATION_FAILED: "JOB_CREATION_FAILED",
90
+ /** Job timed out */
30
91
  JOB_TIMEOUT: "JOB_TIMEOUT",
31
- // Scraping errors
32
- FETCH_FAILED: "FETCH_FAILED",
33
- PARSE_FAILED: "PARSE_FAILED",
34
- BLOCKED_BY_ROBOTS: "BLOCKED_BY_ROBOTS",
35
- CAPTCHA_DETECTED: "CAPTCHA_DETECTED",
36
- SITE_UNREACHABLE: "SITE_UNREACHABLE",
37
- // System errors
92
+ /** Job processing failed */
93
+ JOB_FAILED: "JOB_FAILED",
94
+ /** Job was cancelled */
95
+ JOB_CANCELLED: "JOB_CANCELLED",
96
+ // ============================================
97
+ // Scraping/Crawling (422, 503)
98
+ // ============================================
99
+ /** Failed to fetch URL */
100
+ SCRAPE_FETCH_FAILED: "SCRAPE_FETCH_FAILED",
101
+ /** Failed to parse page content */
102
+ SCRAPE_PARSE_FAILED: "SCRAPE_PARSE_FAILED",
103
+ /** URL is blocked by robots.txt */
104
+ SCRAPE_BLOCKED_BY_ROBOTS: "SCRAPE_BLOCKED_BY_ROBOTS",
105
+ /** CAPTCHA detected on page */
106
+ SCRAPE_CAPTCHA_DETECTED: "SCRAPE_CAPTCHA_DETECTED",
107
+ /** Site is unreachable */
108
+ SCRAPE_SITE_UNREACHABLE: "SCRAPE_SITE_UNREACHABLE",
109
+ /** Scraping operation timed out */
110
+ SCRAPE_TIMEOUT: "SCRAPE_TIMEOUT",
111
+ // Legacy aliases
112
+ /** @deprecated Use SCRAPE_FETCH_FAILED instead */
113
+ FETCH_FAILED: "SCRAPE_FETCH_FAILED",
114
+ /** @deprecated Use SCRAPE_PARSE_FAILED instead */
115
+ PARSE_FAILED: "SCRAPE_PARSE_FAILED",
116
+ /** @deprecated Use SCRAPE_BLOCKED_BY_ROBOTS instead */
117
+ BLOCKED_BY_ROBOTS: "SCRAPE_BLOCKED_BY_ROBOTS",
118
+ /** @deprecated Use SCRAPE_CAPTCHA_DETECTED instead */
119
+ CAPTCHA_DETECTED: "SCRAPE_CAPTCHA_DETECTED",
120
+ /** @deprecated Use SCRAPE_SITE_UNREACHABLE instead */
121
+ SITE_UNREACHABLE: "SCRAPE_SITE_UNREACHABLE",
122
+ // ============================================
123
+ // Webhooks (400, 422)
124
+ // ============================================
125
+ /** A webhook with this event and URL already exists */
126
+ WEBHOOK_ALREADY_EXISTS: "WEBHOOK_ALREADY_EXISTS",
127
+ /** Webhook URL is not valid or not publicly accessible */
128
+ WEBHOOK_INVALID_URL: "WEBHOOK_INVALID_URL",
129
+ /** Webhook replay attack detected */
130
+ WEBHOOK_REPLAY_DETECTED: "WEBHOOK_REPLAY_DETECTED",
131
+ /** Webhook request is too old */
132
+ WEBHOOK_EXPIRED: "WEBHOOK_EXPIRED",
133
+ /** Webhook signature is invalid */
134
+ WEBHOOK_INVALID_SIGNATURE: "WEBHOOK_INVALID_SIGNATURE",
135
+ // ============================================
136
+ // AI Extraction (422)
137
+ // ============================================
138
+ /** AI extraction failed to process content */
139
+ AI_EXTRACTION_FAILED: "AI_EXTRACTION_FAILED",
140
+ /** Failed to parse JSON from AI response */
141
+ AI_JSON_PARSE_FAILED: "AI_JSON_PARSE_FAILED",
142
+ /** AI response did not match expected schema */
143
+ AI_SCHEMA_VALIDATION_FAILED: "AI_SCHEMA_VALIDATION_FAILED",
144
+ /** No price information could be extracted */
145
+ AI_NO_PRICE_FOUND: "AI_NO_PRICE_FOUND",
146
+ /** Extraction confidence is below acceptable threshold */
147
+ AI_LOW_CONFIDENCE: "AI_LOW_CONFIDENCE",
148
+ /** Only partial data could be extracted */
149
+ AI_PARTIAL_RESULT: "AI_PARTIAL_RESULT",
150
+ /** Fallback extraction was used */
151
+ AI_FALLBACK_USED: "AI_FALLBACK_USED",
152
+ /** All fallback strategies failed */
153
+ AI_FALLBACK_FAILED: "AI_FALLBACK_FAILED",
154
+ /** LLM provider rate limit exceeded */
155
+ AI_PROVIDER_RATE_LIMIT: "AI_PROVIDER_RATE_LIMIT",
156
+ /** LLM provider authentication failed */
157
+ AI_PROVIDER_AUTH_FAILED: "AI_PROVIDER_AUTH_FAILED",
158
+ /** LLM provider timeout */
159
+ AI_PROVIDER_TIMEOUT: "AI_PROVIDER_TIMEOUT",
160
+ // ============================================
161
+ // System Errors (500, 503)
162
+ // ============================================
163
+ /** An internal server error occurred */
38
164
  INTERNAL_ERROR: "INTERNAL_ERROR",
39
- SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE",
165
+ /** Database operation failed */
166
+ DATABASE_ERROR: "DATABASE_ERROR",
167
+ /** Redis operation failed */
40
168
  REDIS_ERROR: "REDIS_ERROR",
41
- DATABASE_ERROR: "DATABASE_ERROR"
169
+ /** External service error */
170
+ EXTERNAL_SERVICE_ERROR: "EXTERNAL_SERVICE_ERROR",
171
+ /** Service is temporarily unavailable */
172
+ SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE"
42
173
  };
43
174
  var DealCrawlError = class _DealCrawlError extends Error {
44
175
  /** Error code from ERROR_CODES */
@@ -62,14 +193,19 @@ var DealCrawlError = class _DealCrawlError extends Error {
62
193
  }
63
194
  /**
64
195
  * Check if the error is retryable
65
- * Rate limits and transient errors are retryable
196
+ * Rate limits, transient errors, and AI provider issues are retryable
66
197
  */
67
198
  isRetryable() {
68
199
  const retryableCodes = [
69
200
  ERROR_CODES.RATE_LIMIT_EXCEEDED,
201
+ ERROR_CODES.RATE_CONCURRENT_LIMIT,
70
202
  ERROR_CODES.SERVICE_UNAVAILABLE,
71
203
  ERROR_CODES.REDIS_ERROR,
72
- ERROR_CODES.DATABASE_ERROR
204
+ ERROR_CODES.DATABASE_ERROR,
205
+ ERROR_CODES.EXTERNAL_SERVICE_ERROR,
206
+ ERROR_CODES.AI_PROVIDER_RATE_LIMIT,
207
+ ERROR_CODES.AI_PROVIDER_TIMEOUT,
208
+ ERROR_CODES.SCRAPE_TIMEOUT
73
209
  ];
74
210
  return retryableCodes.includes(this.code);
75
211
  }
@@ -77,25 +213,92 @@ var DealCrawlError = class _DealCrawlError extends Error {
77
213
  * Check if the error is due to authentication issues
78
214
  */
79
215
  isAuthError() {
80
- const authCodes = [
81
- ERROR_CODES.INVALID_API_KEY,
82
- ERROR_CODES.MISSING_API_KEY,
83
- ERROR_CODES.API_KEY_EXPIRED,
84
- ERROR_CODES.ACCOUNT_SUSPENDED
85
- ];
86
- return authCodes.includes(this.code);
216
+ return this.code.startsWith("AUTH_");
87
217
  }
88
218
  /**
89
219
  * Check if the error is due to rate limiting
90
220
  */
91
221
  isRateLimited() {
92
- return this.code === ERROR_CODES.RATE_LIMIT_EXCEEDED;
222
+ return this.code === ERROR_CODES.RATE_LIMIT_EXCEEDED || this.code === ERROR_CODES.RATE_CONCURRENT_LIMIT;
93
223
  }
94
224
  /**
95
225
  * Check if the error is due to quota exceeded
96
226
  */
97
227
  isQuotaExceeded() {
98
- return this.code === ERROR_CODES.QUOTA_EXCEEDED;
228
+ return this.code === ERROR_CODES.RATE_QUOTA_EXCEEDED;
229
+ }
230
+ /**
231
+ * Check if the error is due to AI extraction issues
232
+ */
233
+ isExtractionError() {
234
+ return this.code.startsWith("AI_");
235
+ }
236
+ /**
237
+ * Check if result is partial (some data extracted but incomplete)
238
+ */
239
+ isPartialResult() {
240
+ return this.code === ERROR_CODES.AI_PARTIAL_RESULT || this.code === ERROR_CODES.AI_LOW_CONFIDENCE || this.code === ERROR_CODES.AI_FALLBACK_USED;
241
+ }
242
+ /**
243
+ * Check if extraction failed due to schema validation
244
+ */
245
+ isSchemaValidationError() {
246
+ return this.code === ERROR_CODES.AI_SCHEMA_VALIDATION_FAILED || this.code === ERROR_CODES.AI_JSON_PARSE_FAILED || this.code === ERROR_CODES.VALID_INVALID_SCHEMA;
247
+ }
248
+ /**
249
+ * Check if the error is due to validation issues
250
+ */
251
+ isValidationError() {
252
+ return this.code.startsWith("VALID_");
253
+ }
254
+ /**
255
+ * Check if the error is due to scraping issues
256
+ */
257
+ isScrapeError() {
258
+ return this.code.startsWith("SCRAPE_");
259
+ }
260
+ /**
261
+ * Check if the error is due to webhook issues
262
+ */
263
+ isWebhookError() {
264
+ return this.code.startsWith("WEBHOOK_");
265
+ }
266
+ /**
267
+ * Check if the error is a server error (5xx)
268
+ */
269
+ isServerError() {
270
+ return this.code === ERROR_CODES.INTERNAL_ERROR || this.code === ERROR_CODES.DATABASE_ERROR || this.code === ERROR_CODES.REDIS_ERROR || this.code === ERROR_CODES.EXTERNAL_SERVICE_ERROR || this.code === ERROR_CODES.SERVICE_UNAVAILABLE;
271
+ }
272
+ /**
273
+ * Check if the error is a client error (4xx)
274
+ */
275
+ isClientError() {
276
+ return this.isAuthError() || this.isValidationError() || this.code.startsWith("RESOURCE_") || this.isWebhookError();
277
+ }
278
+ /**
279
+ * Check if fallback was used during extraction
280
+ */
281
+ isFallbackUsed() {
282
+ return this.code === ERROR_CODES.AI_FALLBACK_USED;
283
+ }
284
+ /**
285
+ * Check if all fallback strategies failed
286
+ */
287
+ isFallbackFailed() {
288
+ return this.code === ERROR_CODES.AI_FALLBACK_FAILED;
289
+ }
290
+ /**
291
+ * Check if error is due to AI provider issues
292
+ */
293
+ isAIProviderError() {
294
+ return this.code === ERROR_CODES.AI_PROVIDER_RATE_LIMIT || this.code === ERROR_CODES.AI_PROVIDER_AUTH_FAILED || this.code === ERROR_CODES.AI_PROVIDER_TIMEOUT;
295
+ }
296
+ /**
297
+ * Get extraction-specific error details
298
+ */
299
+ getExtractionDetails() {
300
+ if (!this.isExtractionError()) return void 0;
301
+ return this.details;
99
302
  }
100
303
  /**
101
304
  * Convert error to JSON-serializable object
@@ -137,23 +340,92 @@ var DealCrawlError = class _DealCrawlError extends Error {
137
340
  function mapStatusCodeToErrorCode(statusCode) {
138
341
  switch (statusCode) {
139
342
  case 400:
140
- return ERROR_CODES.INVALID_REQUEST;
343
+ return ERROR_CODES.VALID_INVALID_INPUT;
141
344
  case 401:
142
- return ERROR_CODES.INVALID_API_KEY;
345
+ return ERROR_CODES.AUTH_INVALID_API_KEY;
143
346
  case 403:
144
- return ERROR_CODES.ACCOUNT_SUSPENDED;
347
+ return ERROR_CODES.AUTH_ACCOUNT_SUSPENDED;
145
348
  case 404:
146
- return ERROR_CODES.JOB_NOT_FOUND;
349
+ return ERROR_CODES.RESOURCE_NOT_FOUND;
350
+ case 408:
351
+ return ERROR_CODES.JOB_TIMEOUT;
352
+ case 422:
353
+ return ERROR_CODES.VALID_INVALID_INPUT;
147
354
  case 429:
148
355
  return ERROR_CODES.RATE_LIMIT_EXCEEDED;
149
356
  case 500:
150
357
  return ERROR_CODES.INTERNAL_ERROR;
358
+ case 502:
359
+ return ERROR_CODES.EXTERNAL_SERVICE_ERROR;
151
360
  case 503:
152
361
  return ERROR_CODES.SERVICE_UNAVAILABLE;
153
362
  default:
154
363
  return ERROR_CODES.INTERNAL_ERROR;
155
364
  }
156
365
  }
366
+ var ERROR_MESSAGES = {
367
+ // Authentication
368
+ AUTH_MISSING_HEADER: "Missing or invalid Authorization header",
369
+ AUTH_INVALID_API_KEY: "The provided API key is invalid or expired",
370
+ AUTH_API_KEY_EXPIRED: "Your API key has expired",
371
+ AUTH_API_KEY_REVOKED: "Your API key has been revoked",
372
+ AUTH_INSUFFICIENT_SCOPE: "API key does not have required permissions",
373
+ AUTH_ACCOUNT_SUSPENDED: "Your account has been suspended",
374
+ // Rate Limiting
375
+ RATE_LIMIT_EXCEEDED: "Rate limit exceeded. Please try again later",
376
+ RATE_QUOTA_EXCEEDED: "Monthly quota exceeded. Upgrade your plan for more",
377
+ RATE_CONCURRENT_LIMIT: "Concurrent job limit reached. Wait for existing jobs to complete",
378
+ // Validation
379
+ VALID_INVALID_INPUT: "The provided input is invalid",
380
+ VALID_MISSING_FIELD: "Required field is missing",
381
+ VALID_INVALID_URL: "The provided URL is not valid",
382
+ VALID_INVALID_SCHEMA: "Invalid schema format",
383
+ VALID_INVALID_FORMAT: "Invalid format",
384
+ // Resources
385
+ RESOURCE_NOT_FOUND: "The requested resource was not found",
386
+ RESOURCE_JOB_NOT_FOUND: "Job not found",
387
+ RESOURCE_WEBHOOK_NOT_FOUND: "Webhook not found",
388
+ RESOURCE_KEY_NOT_FOUND: "API key not found",
389
+ // Job Processing
390
+ JOB_CREATION_FAILED: "Failed to create job",
391
+ JOB_TIMEOUT: "Job timed out",
392
+ JOB_FAILED: "Job processing failed",
393
+ JOB_CANCELLED: "Job was cancelled",
394
+ // Scraping
395
+ SCRAPE_FETCH_FAILED: "Failed to fetch URL",
396
+ SCRAPE_PARSE_FAILED: "Failed to parse page content",
397
+ SCRAPE_BLOCKED_BY_ROBOTS: "URL is blocked by robots.txt",
398
+ SCRAPE_CAPTCHA_DETECTED: "CAPTCHA detected on page",
399
+ SCRAPE_SITE_UNREACHABLE: "Site is unreachable",
400
+ SCRAPE_TIMEOUT: "Scraping operation timed out",
401
+ // Webhooks
402
+ WEBHOOK_ALREADY_EXISTS: "A webhook with this event and URL already exists",
403
+ WEBHOOK_INVALID_URL: "Webhook URL is not valid or not publicly accessible",
404
+ WEBHOOK_REPLAY_DETECTED: "Webhook replay attack detected",
405
+ WEBHOOK_EXPIRED: "Webhook request is too old",
406
+ WEBHOOK_INVALID_SIGNATURE: "Webhook signature is invalid",
407
+ // AI Extraction
408
+ AI_EXTRACTION_FAILED: "AI extraction failed to process content",
409
+ AI_JSON_PARSE_FAILED: "Failed to parse JSON from AI response",
410
+ AI_SCHEMA_VALIDATION_FAILED: "AI response did not match expected schema",
411
+ AI_NO_PRICE_FOUND: "No price information could be extracted",
412
+ AI_LOW_CONFIDENCE: "Extraction confidence is below acceptable threshold",
413
+ AI_PARTIAL_RESULT: "Only partial data could be extracted",
414
+ AI_FALLBACK_USED: "Fallback extraction was used",
415
+ AI_FALLBACK_FAILED: "All fallback strategies failed",
416
+ AI_PROVIDER_RATE_LIMIT: "LLM provider rate limit exceeded",
417
+ AI_PROVIDER_AUTH_FAILED: "LLM provider authentication failed",
418
+ AI_PROVIDER_TIMEOUT: "LLM provider timeout",
419
+ // System
420
+ INTERNAL_ERROR: "An internal server error occurred",
421
+ DATABASE_ERROR: "Database operation failed",
422
+ REDIS_ERROR: "Redis operation failed",
423
+ EXTERNAL_SERVICE_ERROR: "External service error",
424
+ SERVICE_UNAVAILABLE: "Service is temporarily unavailable"
425
+ };
426
+ function getErrorMessage(code) {
427
+ return ERROR_MESSAGES[code] || "An unknown error occurred";
428
+ }
157
429
 
158
430
  // src/utils/request.ts
159
431
  function buildQueryString(params) {
@@ -2814,6 +3086,7 @@ exports.DealCrawl = DealCrawl;
2814
3086
  exports.DealCrawlError = DealCrawlError;
2815
3087
  exports.DorkResource = DorkResource;
2816
3088
  exports.ERROR_CODES = ERROR_CODES;
3089
+ exports.ERROR_MESSAGES = ERROR_MESSAGES;
2817
3090
  exports.ExtractResource = ExtractResource;
2818
3091
  exports.KeysResource = KeysResource;
2819
3092
  exports.ScrapeResource = ScrapeResource;
@@ -2821,6 +3094,7 @@ exports.SearchResource = SearchResource;
2821
3094
  exports.StatusResource = StatusResource;
2822
3095
  exports.WebhooksResource = WebhooksResource;
2823
3096
  exports.default = DealCrawl;
3097
+ exports.getErrorMessage = getErrorMessage;
2824
3098
  exports.pollUntil = pollUntil;
2825
3099
  exports.waitForAll = waitForAll;
2826
3100
  exports.waitForAny = waitForAny;