@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/dist/index.mjs CHANGED
@@ -1633,6 +1633,75 @@ var DataResource = class {
1633
1633
  sortOrder: "desc"
1634
1634
  });
1635
1635
  }
1636
+ /**
1637
+ * Get full job details with result
1638
+ *
1639
+ * @example
1640
+ * ```ts
1641
+ * const job = await client.data.getJob("job_abc123");
1642
+ * console.log(job.result);
1643
+ * console.log(job.dealsFound);
1644
+ * ```
1645
+ */
1646
+ async getJob(jobId) {
1647
+ if (!jobId || !jobId.trim()) {
1648
+ throw new Error("jobId is required and cannot be empty");
1649
+ }
1650
+ const result = await get(
1651
+ this.ctx,
1652
+ `/v1/data/jobs/${jobId}`
1653
+ );
1654
+ return result.data;
1655
+ }
1656
+ /**
1657
+ * Get only the result of a completed job
1658
+ *
1659
+ * @example
1660
+ * ```ts
1661
+ * const result = await client.data.getJobResult("job_abc123");
1662
+ * console.log(result.result);
1663
+ * ```
1664
+ */
1665
+ async getJobResult(jobId) {
1666
+ if (!jobId || !jobId.trim()) {
1667
+ throw new Error("jobId is required and cannot be empty");
1668
+ }
1669
+ const result = await get(
1670
+ this.ctx,
1671
+ `/v1/data/jobs/${jobId}/result`
1672
+ );
1673
+ return result.data;
1674
+ }
1675
+ /**
1676
+ * Export job results in various formats
1677
+ * Supports: json, markdown, llm, csv
1678
+ *
1679
+ * @example
1680
+ * ```ts
1681
+ * // Export as JSON
1682
+ * const jsonData = await client.data.exportJob("job_abc123", "json");
1683
+ *
1684
+ * // Export as Markdown
1685
+ * const markdown = await client.data.exportJob("job_abc123", "markdown");
1686
+ *
1687
+ * // Export as LLM-optimized format
1688
+ * const llmText = await client.data.exportJob("job_abc123", "llm");
1689
+ *
1690
+ * // Export as CSV
1691
+ * const csv = await client.data.exportJob("job_abc123", "csv");
1692
+ * ```
1693
+ */
1694
+ async exportJob(jobId, format = "json") {
1695
+ if (!jobId || !jobId.trim()) {
1696
+ throw new Error("jobId is required and cannot be empty");
1697
+ }
1698
+ const result = await get(
1699
+ this.ctx,
1700
+ `/v1/data/jobs/${jobId}/export`,
1701
+ { format }
1702
+ );
1703
+ return result.data;
1704
+ }
1636
1705
  // ============================================
1637
1706
  // DEALS
1638
1707
  // ============================================
@@ -3009,6 +3078,31 @@ var StatusResource = class {
3009
3078
  );
3010
3079
  return result.data;
3011
3080
  }
3081
+ /**
3082
+ * Get errors from a job
3083
+ * Useful for debugging large crawls without loading full results
3084
+ *
3085
+ * @example
3086
+ * ```ts
3087
+ * const errors = await client.status.getJobErrors("job_abc123", {
3088
+ * limit: 50,
3089
+ * offset: 0
3090
+ * });
3091
+ * console.log(errors.data);
3092
+ * console.log(errors.pagination.total);
3093
+ * ```
3094
+ */
3095
+ async getJobErrors(jobId, options) {
3096
+ const result = await get(
3097
+ this.ctx,
3098
+ `/v1/status/${jobId}/errors`,
3099
+ {
3100
+ limit: options?.limit,
3101
+ offset: options?.offset
3102
+ }
3103
+ );
3104
+ return result.data;
3105
+ }
3012
3106
  /**
3013
3107
  * Cancel a pending or active job
3014
3108
  *
@@ -3244,6 +3338,106 @@ var WebhooksResource = class {
3244
3338
  const all = await this.list();
3245
3339
  return all.data.filter((w) => w.event === event);
3246
3340
  }
3341
+ /**
3342
+ * Rotate webhook secret
3343
+ * Rotates the secret while keeping the old one valid during grace period
3344
+ *
3345
+ * @example
3346
+ * ```ts
3347
+ * const result = await client.webhooks.rotateSecret("webhook_abc123", {
3348
+ * newSecret: "new-secure-secret-key",
3349
+ * gracePeriodHours: 24
3350
+ * });
3351
+ * console.log(result.secretVersion);
3352
+ * console.log(result.previousSecretValidUntil);
3353
+ * ```
3354
+ */
3355
+ async rotateSecret(webhookId, options) {
3356
+ if (!webhookId || !webhookId.trim()) {
3357
+ throw new Error("webhookId is required and cannot be empty");
3358
+ }
3359
+ if (!options.newSecret || options.newSecret.length < 16) {
3360
+ throw new Error("newSecret must be at least 16 characters long");
3361
+ }
3362
+ const result = await post(
3363
+ this.ctx,
3364
+ `/v1/webhooks/${webhookId}/rotate`,
3365
+ {
3366
+ newSecret: options.newSecret,
3367
+ gracePeriodHours: options.gracePeriodHours ?? 24
3368
+ }
3369
+ );
3370
+ return result.data;
3371
+ }
3372
+ /**
3373
+ * Get webhook secret rotation status
3374
+ * Check current secret version and grace period status
3375
+ *
3376
+ * @example
3377
+ * ```ts
3378
+ * const status = await client.webhooks.getSecretStatus("webhook_abc123");
3379
+ * console.log(status.secretVersion);
3380
+ * if (status.gracePeriod?.active) {
3381
+ * console.log(`Grace period expires: ${status.gracePeriod.expiresAt}`);
3382
+ * }
3383
+ * ```
3384
+ */
3385
+ async getSecretStatus(webhookId) {
3386
+ if (!webhookId || !webhookId.trim()) {
3387
+ throw new Error("webhookId is required and cannot be empty");
3388
+ }
3389
+ const result = await get(
3390
+ this.ctx,
3391
+ `/v1/webhooks/${webhookId}/secret-status`
3392
+ );
3393
+ return result.data;
3394
+ }
3395
+ /**
3396
+ * Verify webhook signature and replay protection
3397
+ * Validates signature, timestamp, and nonce from received webhook
3398
+ *
3399
+ * @example
3400
+ * ```ts
3401
+ * const isValid = await client.webhooks.verifySignature({
3402
+ * webhookId: "webhook_abc123",
3403
+ * payload: receivedPayload,
3404
+ * signature: headers["x-dealcrawl-signature"],
3405
+ * timestamp: parseInt(headers["x-dealcrawl-timestamp"]),
3406
+ * nonce: headers["x-dealcrawl-nonce"]
3407
+ * });
3408
+ * if (isValid.valid) {
3409
+ * console.log("Webhook is valid");
3410
+ * } else {
3411
+ * console.log(`Invalid: ${isValid.error}`);
3412
+ * }
3413
+ * ```
3414
+ */
3415
+ async verifySignature(options) {
3416
+ if (!options.webhookId || !options.webhookId.trim()) {
3417
+ throw new Error("webhookId is required and cannot be empty");
3418
+ }
3419
+ if (!options.signature) {
3420
+ throw new Error("signature is required");
3421
+ }
3422
+ if (!options.timestamp || options.timestamp <= 0) {
3423
+ throw new Error("timestamp is required and must be positive");
3424
+ }
3425
+ if (!options.nonce || !/^[0-9a-f]{32}$/i.test(options.nonce)) {
3426
+ throw new Error("nonce must be a 32-character hex string");
3427
+ }
3428
+ const result = await post(
3429
+ this.ctx,
3430
+ "/v1/webhooks/verify",
3431
+ {
3432
+ webhookId: options.webhookId,
3433
+ payload: options.payload,
3434
+ signature: options.signature,
3435
+ timestamp: options.timestamp,
3436
+ nonce: options.nonce
3437
+ }
3438
+ );
3439
+ return result.data;
3440
+ }
3247
3441
  };
3248
3442
 
3249
3443
  // src/client.ts