@stack0/sdk 0.2.9 → 0.3.1

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 (42) hide show
  1. package/README.md +233 -10
  2. package/dist/cdn/index.d.mts +239 -26
  3. package/dist/cdn/index.d.ts +239 -26
  4. package/dist/cdn/index.js +219 -20
  5. package/dist/cdn/index.js.map +1 -1
  6. package/dist/cdn/index.mjs +219 -20
  7. package/dist/cdn/index.mjs.map +1 -1
  8. package/dist/extraction/index.d.mts +1 -1
  9. package/dist/extraction/index.d.ts +1 -1
  10. package/dist/extraction/index.js +33 -29
  11. package/dist/extraction/index.js.map +1 -1
  12. package/dist/extraction/index.mjs +33 -29
  13. package/dist/extraction/index.mjs.map +1 -1
  14. package/dist/http-client-Cgie_Rv6.d.mts +25 -0
  15. package/dist/http-client-Cgie_Rv6.d.ts +25 -0
  16. package/dist/index.d.mts +1006 -3
  17. package/dist/index.d.ts +1006 -3
  18. package/dist/index.js +958 -69
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs +957 -70
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/mail/index.d.mts +1 -1
  23. package/dist/mail/index.d.ts +1 -1
  24. package/dist/mail/index.js +13 -5
  25. package/dist/mail/index.js.map +1 -1
  26. package/dist/mail/index.mjs +13 -5
  27. package/dist/mail/index.mjs.map +1 -1
  28. package/dist/screenshots/index.d.mts +1 -1
  29. package/dist/screenshots/index.d.ts +1 -1
  30. package/dist/screenshots/index.js +32 -26
  31. package/dist/screenshots/index.js.map +1 -1
  32. package/dist/screenshots/index.mjs +32 -26
  33. package/dist/screenshots/index.mjs.map +1 -1
  34. package/dist/webdata/index.d.mts +1 -1
  35. package/dist/webdata/index.d.ts +1 -1
  36. package/dist/webdata/index.js +37 -8
  37. package/dist/webdata/index.js.map +1 -1
  38. package/dist/webdata/index.mjs +37 -8
  39. package/dist/webdata/index.mjs.map +1 -1
  40. package/package.json +1 -1
  41. package/dist/http-client-Wr9lXo9_.d.mts +0 -10
  42. package/dist/http-client-Wr9lXo9_.d.ts +0 -10
package/dist/index.mjs CHANGED
@@ -6,19 +6,24 @@ var HttpClient = class {
6
6
  this.apiKey = config.apiKey;
7
7
  this.baseUrl = config.baseUrl || "https://api.stack0.dev/v1";
8
8
  }
9
- getHeaders() {
10
- return {
11
- "Content-Type": "application/json",
9
+ getHeaders(includeContentType = true) {
10
+ const headers = {
12
11
  Authorization: `Bearer ${this.apiKey}`
13
12
  };
13
+ if (includeContentType) {
14
+ headers["Content-Type"] = "application/json";
15
+ }
16
+ return headers;
14
17
  }
15
18
  async request(method, path, body) {
16
19
  const url = `${this.baseUrl}${path}`;
20
+ const bodyString = body === void 0 ? void 0 : JSON.stringify(body);
21
+ const hasBody = bodyString !== void 0;
17
22
  try {
18
23
  const response = await fetch(url, {
19
24
  method,
20
- headers: this.getHeaders(),
21
- body: body ? JSON.stringify(body) : void 0
25
+ headers: this.getHeaders(hasBody),
26
+ body: hasBody ? bodyString : void 0
22
27
  });
23
28
  if (!response.ok) {
24
29
  await this.handleErrorResponse(response);
@@ -62,6 +67,9 @@ var HttpClient = class {
62
67
  async delete(path) {
63
68
  return this.request("DELETE", path);
64
69
  }
70
+ async deleteWithBody(path, body) {
71
+ return this.request("DELETE", path, body);
72
+ }
65
73
  async patch(path, body) {
66
74
  return this.request("PATCH", path, body);
67
75
  }
@@ -115,10 +123,13 @@ var Mail = class {
115
123
  };
116
124
 
117
125
  // src/cdn/client.ts
126
+ var ALLOWED_WIDTHS = [256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840];
118
127
  var CDN = class {
119
128
  http;
120
- constructor(config) {
129
+ cdnUrl;
130
+ constructor(config, cdnUrl) {
121
131
  this.http = new HttpClient(config);
132
+ this.cdnUrl = cdnUrl;
122
133
  }
123
134
  /**
124
135
  * Generate a presigned URL for uploading a file
@@ -239,7 +250,7 @@ var CDN = class {
239
250
  * ```
240
251
  */
241
252
  async delete(id) {
242
- return this.http.delete(`/cdn/assets/${id}`);
253
+ return this.http.deleteWithBody(`/cdn/assets/${id}`, { id });
243
254
  }
244
255
  /**
245
256
  * Delete multiple assets
@@ -298,24 +309,73 @@ var CDN = class {
298
309
  return this.http.post("/cdn/assets/move", request);
299
310
  }
300
311
  /**
301
- * Get a transformed image URL
312
+ * Get a transformed image URL (client-side, no API call)
302
313
  *
303
314
  * @example
304
315
  * ```typescript
305
- * const { url } = await cdn.getTransformUrl({
306
- * assetId: 'asset-id',
307
- * options: {
308
- * width: 800,
309
- * height: 600,
310
- * fit: 'cover',
311
- * format: 'webp',
312
- * quality: 80,
313
- * },
316
+ * // Using asset's cdnUrl directly
317
+ * const url = cdn.getTransformUrl(asset.cdnUrl, {
318
+ * width: 800,
319
+ * height: 600,
320
+ * fit: 'cover',
321
+ * format: 'webp',
322
+ * quality: 80,
314
323
  * });
324
+ *
325
+ * // Or using cdnUrl from SDK config + s3Key
326
+ * const url = cdn.getTransformUrl(asset.s3Key, { width: 400 });
315
327
  * ```
316
328
  */
317
- async getTransformUrl(request) {
318
- return this.http.post("/cdn/transform", request);
329
+ getTransformUrl(assetUrlOrS3Key, options) {
330
+ let baseUrl;
331
+ if (assetUrlOrS3Key.startsWith("http://") || assetUrlOrS3Key.startsWith("https://")) {
332
+ const url = new URL(assetUrlOrS3Key);
333
+ baseUrl = `${url.protocol}//${url.host}${url.pathname}`;
334
+ } else if (this.cdnUrl) {
335
+ const cdnBase = this.cdnUrl.endsWith("/") ? this.cdnUrl.slice(0, -1) : this.cdnUrl;
336
+ baseUrl = `${cdnBase}/${assetUrlOrS3Key}`;
337
+ } else {
338
+ throw new Error("getTransformUrl requires either a full URL or cdnUrl to be configured in Stack0 options");
339
+ }
340
+ const params = this.buildTransformQuery(options);
341
+ if (!params) {
342
+ return baseUrl;
343
+ }
344
+ return `${baseUrl}?${params}`;
345
+ }
346
+ /**
347
+ * Build transform query parameters
348
+ */
349
+ buildTransformQuery(options) {
350
+ const params = new URLSearchParams();
351
+ if (options.format) params.set("f", options.format);
352
+ if (options.quality !== void 0) params.set("q", options.quality.toString());
353
+ if (options.width !== void 0) {
354
+ const width = this.getNearestWidth(options.width);
355
+ params.set("w", width.toString());
356
+ }
357
+ if (options.height !== void 0) params.set("h", options.height.toString());
358
+ if (options.fit) params.set("fit", options.fit);
359
+ if (options.crop) params.set("crop", options.crop);
360
+ if (options.cropX !== void 0) params.set("crop-x", options.cropX.toString());
361
+ if (options.cropY !== void 0) params.set("crop-y", options.cropY.toString());
362
+ if (options.cropWidth !== void 0) params.set("crop-w", options.cropWidth.toString());
363
+ if (options.cropHeight !== void 0) params.set("crop-h", options.cropHeight.toString());
364
+ if (options.blur !== void 0) params.set("blur", options.blur.toString());
365
+ if (options.sharpen !== void 0) params.set("sharpen", options.sharpen.toString());
366
+ if (options.brightness !== void 0) params.set("brightness", options.brightness.toString());
367
+ if (options.saturation !== void 0) params.set("saturation", options.saturation.toString());
368
+ if (options.grayscale) params.set("grayscale", "true");
369
+ if (options.rotate !== void 0) params.set("rotate", options.rotate.toString());
370
+ if (options.flip) params.set("flip", "y");
371
+ if (options.flop) params.set("flop", "x");
372
+ return params.toString();
373
+ }
374
+ /**
375
+ * Find the nearest allowed width for optimal caching
376
+ */
377
+ getNearestWidth(width) {
378
+ return ALLOWED_WIDTHS.reduce((prev, curr) => Math.abs(curr - width) < Math.abs(prev - width) ? curr : prev);
319
379
  }
320
380
  /**
321
381
  * Get folder tree for navigation
@@ -361,7 +421,10 @@ var CDN = class {
361
421
  async deleteFolder(id, deleteContents = false) {
362
422
  const params = new URLSearchParams();
363
423
  if (deleteContents) params.set("deleteContents", "true");
364
- return this.http.delete(`/cdn/folders/${id}?${params.toString()}`);
424
+ return this.http.deleteWithBody(`/cdn/folders/${id}?${params.toString()}`, {
425
+ id,
426
+ deleteContents
427
+ });
365
428
  }
366
429
  convertAssetDates(asset) {
367
430
  if (typeof asset.createdAt === "string") {
@@ -381,6 +444,142 @@ var CDN = class {
381
444
  }
382
445
  return folder;
383
446
  }
447
+ // ============================================================================
448
+ // Video Transcoding Methods
449
+ // ============================================================================
450
+ /**
451
+ * Start a video transcoding job
452
+ *
453
+ * @example
454
+ * ```typescript
455
+ * const job = await cdn.transcode({
456
+ * projectSlug: 'my-project',
457
+ * assetId: 'video-asset-id',
458
+ * outputFormat: 'hls',
459
+ * variants: [
460
+ * { quality: '720p', codec: 'h264' },
461
+ * { quality: '1080p', codec: 'h264' },
462
+ * ],
463
+ * webhookUrl: 'https://your-app.com/webhook',
464
+ * });
465
+ * console.log(`Job started: ${job.id}`);
466
+ * ```
467
+ */
468
+ async transcode(request) {
469
+ const response = await this.http.post("/cdn/video/transcode", request);
470
+ return this.convertJobDates(response);
471
+ }
472
+ /**
473
+ * Get a transcoding job by ID
474
+ *
475
+ * @example
476
+ * ```typescript
477
+ * const job = await cdn.getJob('job-id');
478
+ * console.log(`Status: ${job.status}, Progress: ${job.progress}%`);
479
+ * ```
480
+ */
481
+ async getJob(jobId) {
482
+ const response = await this.http.get(`/cdn/video/jobs/${jobId}`);
483
+ return this.convertJobDates(response);
484
+ }
485
+ /**
486
+ * List transcoding jobs with filters
487
+ *
488
+ * @example
489
+ * ```typescript
490
+ * const { jobs, total } = await cdn.listJobs({
491
+ * projectSlug: 'my-project',
492
+ * status: 'processing',
493
+ * limit: 20,
494
+ * });
495
+ * ```
496
+ */
497
+ async listJobs(request) {
498
+ const params = new URLSearchParams();
499
+ params.set("projectSlug", request.projectSlug);
500
+ if (request.assetId) params.set("assetId", request.assetId);
501
+ if (request.status) params.set("status", request.status);
502
+ if (request.limit) params.set("limit", request.limit.toString());
503
+ if (request.offset) params.set("offset", request.offset.toString());
504
+ const response = await this.http.get(`/cdn/video/jobs?${params.toString()}`);
505
+ return {
506
+ ...response,
507
+ jobs: response.jobs.map((job) => this.convertJobDates(job))
508
+ };
509
+ }
510
+ /**
511
+ * Cancel a pending or processing transcoding job
512
+ *
513
+ * @example
514
+ * ```typescript
515
+ * await cdn.cancelJob('job-id');
516
+ * ```
517
+ */
518
+ async cancelJob(jobId) {
519
+ return this.http.post(`/cdn/video/jobs/${jobId}/cancel`, {});
520
+ }
521
+ /**
522
+ * Get streaming URLs for a transcoded video
523
+ *
524
+ * @example
525
+ * ```typescript
526
+ * const urls = await cdn.getStreamingUrls('asset-id');
527
+ * console.log(`HLS URL: ${urls.hlsUrl}`);
528
+ * console.log(`MP4 720p: ${urls.mp4Urls.find(u => u.quality === '720p')?.url}`);
529
+ * ```
530
+ */
531
+ async getStreamingUrls(assetId) {
532
+ return this.http.get(`/cdn/video/stream/${assetId}`);
533
+ }
534
+ /**
535
+ * Generate a thumbnail from a video at a specific timestamp
536
+ *
537
+ * @example
538
+ * ```typescript
539
+ * const thumbnail = await cdn.getThumbnail({
540
+ * assetId: 'video-asset-id',
541
+ * timestamp: 10.5, // 10.5 seconds into the video
542
+ * width: 320,
543
+ * format: 'webp',
544
+ * });
545
+ * console.log(`Thumbnail URL: ${thumbnail.url}`);
546
+ * ```
547
+ */
548
+ async getThumbnail(request) {
549
+ const params = new URLSearchParams();
550
+ params.set("timestamp", request.timestamp.toString());
551
+ if (request.width) params.set("width", request.width.toString());
552
+ if (request.format) params.set("format", request.format);
553
+ return this.http.get(`/cdn/video/thumbnail/${request.assetId}?${params.toString()}`);
554
+ }
555
+ /**
556
+ * Extract audio from a video file
557
+ *
558
+ * @example
559
+ * ```typescript
560
+ * const { jobId } = await cdn.extractAudio({
561
+ * projectSlug: 'my-project',
562
+ * assetId: 'video-asset-id',
563
+ * format: 'mp3',
564
+ * bitrate: 192,
565
+ * });
566
+ * ```
567
+ */
568
+ async extractAudio(request) {
569
+ return this.http.post("/cdn/video/extract-audio", request);
570
+ }
571
+ convertJobDates(job) {
572
+ if (typeof job.createdAt === "string") {
573
+ job.createdAt = new Date(job.createdAt);
574
+ }
575
+ if (job.startedAt && typeof job.startedAt === "string") {
576
+ job.startedAt = new Date(job.startedAt);
577
+ }
578
+ if (job.completedAt && typeof job.completedAt === "string") {
579
+ job.completedAt = new Date(job.completedAt);
580
+ }
581
+ return job;
582
+ }
384
583
  };
385
584
 
386
585
  // src/screenshots/client.ts
@@ -452,9 +651,7 @@ var Screenshots = class {
452
651
  if (request.limit) params.set("limit", request.limit.toString());
453
652
  if (request.cursor) params.set("cursor", request.cursor);
454
653
  const query = params.toString();
455
- const response = await this.http.get(
456
- `/webdata/screenshots${query ? `?${query}` : ""}`
457
- );
654
+ const response = await this.http.get(`/webdata/screenshots${query ? `?${query}` : ""}`);
458
655
  return {
459
656
  ...response,
460
657
  items: response.items.map((item) => this.convertDates(item))
@@ -473,8 +670,13 @@ var Screenshots = class {
473
670
  if (request.environment) params.set("environment", request.environment);
474
671
  if (request.projectId) params.set("projectId", request.projectId);
475
672
  const query = params.toString();
476
- return this.http.delete(
477
- `/webdata/screenshots/${request.id}${query ? `?${query}` : ""}`
673
+ return this.http.deleteWithBody(
674
+ `/webdata/screenshots/${request.id}${query ? `?${query}` : ""}`,
675
+ {
676
+ id: request.id,
677
+ environment: request.environment,
678
+ projectId: request.projectId
679
+ }
478
680
  );
479
681
  }
480
682
  /**
@@ -557,9 +759,7 @@ var Screenshots = class {
557
759
  if (request.limit) params.set("limit", request.limit.toString());
558
760
  if (request.cursor) params.set("cursor", request.cursor);
559
761
  const query = params.toString();
560
- const response = await this.http.get(
561
- `/webdata/batch${query ? `?${query}` : ""}`
562
- );
762
+ const response = await this.http.get(`/webdata/batch${query ? `?${query}` : ""}`);
563
763
  return {
564
764
  ...response,
565
765
  items: response.items.map((item) => this.convertBatchJobDates(item))
@@ -573,10 +773,7 @@ var Screenshots = class {
573
773
  if (request.environment) params.set("environment", request.environment);
574
774
  if (request.projectId) params.set("projectId", request.projectId);
575
775
  const query = params.toString();
576
- return this.http.post(
577
- `/webdata/batch/${request.id}/cancel${query ? `?${query}` : ""}`,
578
- {}
579
- );
776
+ return this.http.post(`/webdata/batch/${request.id}/cancel${query ? `?${query}` : ""}`, {});
580
777
  }
581
778
  /**
582
779
  * Create a batch screenshot job and wait for completion
@@ -629,10 +826,7 @@ var Screenshots = class {
629
826
  if (environment) params.set("environment", environment);
630
827
  if (projectId) params.set("projectId", projectId);
631
828
  const query = params.toString();
632
- return this.http.post(
633
- `/webdata/schedules/${id}${query ? `?${query}` : ""}`,
634
- data
635
- );
829
+ return this.http.post(`/webdata/schedules/${id}${query ? `?${query}` : ""}`, data);
636
830
  }
637
831
  /**
638
832
  * Get a schedule by ID
@@ -658,9 +852,7 @@ var Screenshots = class {
658
852
  if (request.limit) params.set("limit", request.limit.toString());
659
853
  if (request.cursor) params.set("cursor", request.cursor);
660
854
  const query = params.toString();
661
- const response = await this.http.get(
662
- `/webdata/schedules${query ? `?${query}` : ""}`
663
- );
855
+ const response = await this.http.get(`/webdata/schedules${query ? `?${query}` : ""}`);
664
856
  return {
665
857
  ...response,
666
858
  items: response.items.map((item) => this.convertScheduleDates(item))
@@ -674,8 +866,13 @@ var Screenshots = class {
674
866
  if (request.environment) params.set("environment", request.environment);
675
867
  if (request.projectId) params.set("projectId", request.projectId);
676
868
  const query = params.toString();
677
- return this.http.delete(
678
- `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`
869
+ return this.http.deleteWithBody(
870
+ `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`,
871
+ {
872
+ id: request.id,
873
+ environment: request.environment,
874
+ projectId: request.projectId
875
+ }
679
876
  );
680
877
  }
681
878
  /**
@@ -801,9 +998,7 @@ var Extraction = class {
801
998
  if (request.limit) params.set("limit", request.limit.toString());
802
999
  if (request.cursor) params.set("cursor", request.cursor);
803
1000
  const query = params.toString();
804
- const response = await this.http.get(
805
- `/webdata/extractions${query ? `?${query}` : ""}`
806
- );
1001
+ const response = await this.http.get(`/webdata/extractions${query ? `?${query}` : ""}`);
807
1002
  return {
808
1003
  ...response,
809
1004
  items: response.items.map((item) => this.convertDates(item))
@@ -822,8 +1017,13 @@ var Extraction = class {
822
1017
  if (request.environment) params.set("environment", request.environment);
823
1018
  if (request.projectId) params.set("projectId", request.projectId);
824
1019
  const query = params.toString();
825
- return this.http.delete(
826
- `/webdata/extractions/${request.id}${query ? `?${query}` : ""}`
1020
+ return this.http.deleteWithBody(
1021
+ `/webdata/extractions/${request.id}${query ? `?${query}` : ""}`,
1022
+ {
1023
+ id: request.id,
1024
+ environment: request.environment,
1025
+ projectId: request.projectId
1026
+ }
827
1027
  );
828
1028
  }
829
1029
  /**
@@ -902,9 +1102,7 @@ var Extraction = class {
902
1102
  if (request.limit) params.set("limit", request.limit.toString());
903
1103
  if (request.cursor) params.set("cursor", request.cursor);
904
1104
  const query = params.toString();
905
- const response = await this.http.get(
906
- `/webdata/batch${query ? `?${query}` : ""}`
907
- );
1105
+ const response = await this.http.get(`/webdata/batch${query ? `?${query}` : ""}`);
908
1106
  return {
909
1107
  ...response,
910
1108
  items: response.items.map((item) => this.convertBatchJobDates(item))
@@ -918,10 +1116,7 @@ var Extraction = class {
918
1116
  if (request.environment) params.set("environment", request.environment);
919
1117
  if (request.projectId) params.set("projectId", request.projectId);
920
1118
  const query = params.toString();
921
- return this.http.post(
922
- `/webdata/batch/${request.id}/cancel${query ? `?${query}` : ""}`,
923
- {}
924
- );
1119
+ return this.http.post(`/webdata/batch/${request.id}/cancel${query ? `?${query}` : ""}`, {});
925
1120
  }
926
1121
  /**
927
1122
  * Create a batch extraction job and wait for completion
@@ -974,10 +1169,7 @@ var Extraction = class {
974
1169
  if (environment) params.set("environment", environment);
975
1170
  if (projectId) params.set("projectId", projectId);
976
1171
  const query = params.toString();
977
- return this.http.post(
978
- `/webdata/schedules/${id}${query ? `?${query}` : ""}`,
979
- data
980
- );
1172
+ return this.http.post(`/webdata/schedules/${id}${query ? `?${query}` : ""}`, data);
981
1173
  }
982
1174
  /**
983
1175
  * Get a schedule by ID
@@ -1003,9 +1195,7 @@ var Extraction = class {
1003
1195
  if (request.limit) params.set("limit", request.limit.toString());
1004
1196
  if (request.cursor) params.set("cursor", request.cursor);
1005
1197
  const query = params.toString();
1006
- const response = await this.http.get(
1007
- `/webdata/schedules${query ? `?${query}` : ""}`
1008
- );
1198
+ const response = await this.http.get(`/webdata/schedules${query ? `?${query}` : ""}`);
1009
1199
  return {
1010
1200
  ...response,
1011
1201
  items: response.items.map((item) => this.convertScheduleDates(item))
@@ -1019,8 +1209,13 @@ var Extraction = class {
1019
1209
  if (request.environment) params.set("environment", request.environment);
1020
1210
  if (request.projectId) params.set("projectId", request.projectId);
1021
1211
  const query = params.toString();
1022
- return this.http.delete(
1023
- `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`
1212
+ return this.http.deleteWithBody(
1213
+ `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`,
1214
+ {
1215
+ id: request.id,
1216
+ environment: request.environment,
1217
+ projectId: request.projectId
1218
+ }
1024
1219
  );
1025
1220
  }
1026
1221
  /**
@@ -1058,9 +1253,7 @@ var Extraction = class {
1058
1253
  if (request.periodStart) params.set("periodStart", request.periodStart);
1059
1254
  if (request.periodEnd) params.set("periodEnd", request.periodEnd);
1060
1255
  const query = params.toString();
1061
- const response = await this.http.get(
1062
- `/webdata/usage${query ? `?${query}` : ""}`
1063
- );
1256
+ const response = await this.http.get(`/webdata/usage${query ? `?${query}` : ""}`);
1064
1257
  return this.convertUsageDates(response);
1065
1258
  }
1066
1259
  // ==========================================================================
@@ -1201,7 +1394,14 @@ var Webdata = class {
1201
1394
  if (request.environment) params.set("environment", request.environment);
1202
1395
  if (request.projectId) params.set("projectId", request.projectId);
1203
1396
  const query = params.toString();
1204
- return this.http.delete(`/webdata/screenshots/${request.id}${query ? `?${query}` : ""}`);
1397
+ return this.http.deleteWithBody(
1398
+ `/webdata/screenshots/${request.id}${query ? `?${query}` : ""}`,
1399
+ {
1400
+ id: request.id,
1401
+ environment: request.environment,
1402
+ projectId: request.projectId
1403
+ }
1404
+ );
1205
1405
  }
1206
1406
  /**
1207
1407
  * Capture a screenshot and wait for completion
@@ -1317,7 +1517,14 @@ var Webdata = class {
1317
1517
  if (request.environment) params.set("environment", request.environment);
1318
1518
  if (request.projectId) params.set("projectId", request.projectId);
1319
1519
  const query = params.toString();
1320
- return this.http.delete(`/webdata/extractions/${request.id}${query ? `?${query}` : ""}`);
1520
+ return this.http.deleteWithBody(
1521
+ `/webdata/extractions/${request.id}${query ? `?${query}` : ""}`,
1522
+ {
1523
+ id: request.id,
1524
+ environment: request.environment,
1525
+ projectId: request.projectId
1526
+ }
1527
+ );
1321
1528
  }
1322
1529
  /**
1323
1530
  * Extract content and wait for completion
@@ -1448,7 +1655,14 @@ var Webdata = class {
1448
1655
  if (request.environment) params.set("environment", request.environment);
1449
1656
  if (request.projectId) params.set("projectId", request.projectId);
1450
1657
  const query = params.toString();
1451
- return this.http.delete(`/webdata/schedules/${request.id}${query ? `?${query}` : ""}`);
1658
+ return this.http.deleteWithBody(
1659
+ `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`,
1660
+ {
1661
+ id: request.id,
1662
+ environment: request.environment,
1663
+ projectId: request.projectId
1664
+ }
1665
+ );
1452
1666
  }
1453
1667
  /**
1454
1668
  * Toggle a schedule on or off
@@ -1713,12 +1927,683 @@ var Webdata = class {
1713
1927
  }
1714
1928
  };
1715
1929
 
1930
+ // src/integrations/client.ts
1931
+ var CRM = class {
1932
+ http;
1933
+ constructor(http) {
1934
+ this.http = http;
1935
+ }
1936
+ // Contacts
1937
+ async listContacts(connectionId, options) {
1938
+ const params = new URLSearchParams({ connectionId });
1939
+ if (options?.cursor) params.set("cursor", options.cursor);
1940
+ if (options?.limit) params.set("limit", String(options.limit));
1941
+ if (options?.sortBy) params.set("sortBy", options.sortBy);
1942
+ if (options?.sortOrder) params.set("sortOrder", options.sortOrder);
1943
+ return this.http.get(`/integrations/crm/contacts?${params}`);
1944
+ }
1945
+ async getContact(connectionId, id) {
1946
+ return this.http.get(`/integrations/crm/contacts/${id}?connectionId=${connectionId}`);
1947
+ }
1948
+ async createContact(connectionId, data) {
1949
+ return this.http.post("/integrations/crm/contacts", { connectionId, data });
1950
+ }
1951
+ async updateContact(connectionId, id, data) {
1952
+ return this.http.patch(`/integrations/crm/contacts/${id}`, { connectionId, data });
1953
+ }
1954
+ async deleteContact(connectionId, id) {
1955
+ return this.http.delete(`/integrations/crm/contacts/${id}?connectionId=${connectionId}`);
1956
+ }
1957
+ // Companies
1958
+ async listCompanies(connectionId, options) {
1959
+ const params = new URLSearchParams({ connectionId });
1960
+ if (options?.cursor) params.set("cursor", options.cursor);
1961
+ if (options?.limit) params.set("limit", String(options.limit));
1962
+ if (options?.sortBy) params.set("sortBy", options.sortBy);
1963
+ if (options?.sortOrder) params.set("sortOrder", options.sortOrder);
1964
+ return this.http.get(`/integrations/crm/companies?${params}`);
1965
+ }
1966
+ async getCompany(connectionId, id) {
1967
+ return this.http.get(`/integrations/crm/companies/${id}?connectionId=${connectionId}`);
1968
+ }
1969
+ async createCompany(connectionId, data) {
1970
+ return this.http.post("/integrations/crm/companies", { connectionId, data });
1971
+ }
1972
+ async updateCompany(connectionId, id, data) {
1973
+ return this.http.patch(`/integrations/crm/companies/${id}`, { connectionId, data });
1974
+ }
1975
+ async deleteCompany(connectionId, id) {
1976
+ return this.http.delete(`/integrations/crm/companies/${id}?connectionId=${connectionId}`);
1977
+ }
1978
+ // Deals
1979
+ async listDeals(connectionId, options) {
1980
+ const params = new URLSearchParams({ connectionId });
1981
+ if (options?.cursor) params.set("cursor", options.cursor);
1982
+ if (options?.limit) params.set("limit", String(options.limit));
1983
+ if (options?.sortBy) params.set("sortBy", options.sortBy);
1984
+ if (options?.sortOrder) params.set("sortOrder", options.sortOrder);
1985
+ return this.http.get(`/integrations/crm/deals?${params}`);
1986
+ }
1987
+ async getDeal(connectionId, id) {
1988
+ return this.http.get(`/integrations/crm/deals/${id}?connectionId=${connectionId}`);
1989
+ }
1990
+ async createDeal(connectionId, data) {
1991
+ return this.http.post("/integrations/crm/deals", { connectionId, data });
1992
+ }
1993
+ async updateDeal(connectionId, id, data) {
1994
+ return this.http.patch(`/integrations/crm/deals/${id}`, { connectionId, data });
1995
+ }
1996
+ async deleteDeal(connectionId, id) {
1997
+ return this.http.delete(`/integrations/crm/deals/${id}?connectionId=${connectionId}`);
1998
+ }
1999
+ };
2000
+ var Storage = class {
2001
+ http;
2002
+ constructor(http) {
2003
+ this.http = http;
2004
+ }
2005
+ // Files
2006
+ async listFiles(connectionId, folderId, options) {
2007
+ const params = new URLSearchParams({ connectionId });
2008
+ if (folderId) params.set("folderId", folderId);
2009
+ if (options?.cursor) params.set("cursor", options.cursor);
2010
+ if (options?.limit) params.set("limit", String(options.limit));
2011
+ return this.http.get(`/integrations/storage/files?${params}`);
2012
+ }
2013
+ async getFile(connectionId, id) {
2014
+ return this.http.get(`/integrations/storage/files/${id}?connectionId=${connectionId}`);
2015
+ }
2016
+ async uploadFile(connectionId, input) {
2017
+ const base64Data = input.data instanceof ArrayBuffer ? btoa(String.fromCharCode(...new Uint8Array(input.data))) : btoa(String.fromCharCode(...input.data));
2018
+ return this.http.post("/integrations/storage/files", {
2019
+ connectionId,
2020
+ name: input.name,
2021
+ mimeType: input.mimeType,
2022
+ data: base64Data,
2023
+ folderId: input.folderId
2024
+ });
2025
+ }
2026
+ async deleteFile(connectionId, id) {
2027
+ return this.http.delete(`/integrations/storage/files/${id}?connectionId=${connectionId}`);
2028
+ }
2029
+ async downloadFile(connectionId, id) {
2030
+ const response = await this.http.get(
2031
+ `/integrations/storage/files/${id}/download?connectionId=${connectionId}`
2032
+ );
2033
+ const binaryString = atob(response.data);
2034
+ const bytes = new Uint8Array(binaryString.length);
2035
+ for (let i = 0; i < binaryString.length; i++) {
2036
+ bytes[i] = binaryString.charCodeAt(i);
2037
+ }
2038
+ return {
2039
+ data: bytes.buffer,
2040
+ mimeType: response.mimeType,
2041
+ filename: response.filename
2042
+ };
2043
+ }
2044
+ // Folders
2045
+ async listFolders(connectionId, parentId, options) {
2046
+ const params = new URLSearchParams({ connectionId });
2047
+ if (parentId) params.set("parentId", parentId);
2048
+ if (options?.cursor) params.set("cursor", options.cursor);
2049
+ if (options?.limit) params.set("limit", String(options.limit));
2050
+ return this.http.get(`/integrations/storage/folders?${params}`);
2051
+ }
2052
+ async getFolder(connectionId, id) {
2053
+ return this.http.get(`/integrations/storage/folders/${id}?connectionId=${connectionId}`);
2054
+ }
2055
+ async createFolder(connectionId, data) {
2056
+ return this.http.post("/integrations/storage/folders", { connectionId, ...data });
2057
+ }
2058
+ async deleteFolder(connectionId, id) {
2059
+ return this.http.delete(`/integrations/storage/folders/${id}?connectionId=${connectionId}`);
2060
+ }
2061
+ };
2062
+ var Communication = class {
2063
+ http;
2064
+ constructor(http) {
2065
+ this.http = http;
2066
+ }
2067
+ // Channels
2068
+ async listChannels(connectionId, options) {
2069
+ const params = new URLSearchParams({ connectionId });
2070
+ if (options?.cursor) params.set("cursor", options.cursor);
2071
+ if (options?.limit) params.set("limit", String(options.limit));
2072
+ return this.http.get(`/integrations/communication/channels?${params}`);
2073
+ }
2074
+ async getChannel(connectionId, id) {
2075
+ return this.http.get(`/integrations/communication/channels/${id}?connectionId=${connectionId}`);
2076
+ }
2077
+ // Messages
2078
+ async listMessages(connectionId, channelId, options) {
2079
+ const params = new URLSearchParams({ connectionId, channelId });
2080
+ if (options?.cursor) params.set("cursor", options.cursor);
2081
+ if (options?.limit) params.set("limit", String(options.limit));
2082
+ return this.http.get(`/integrations/communication/messages?${params}`);
2083
+ }
2084
+ async sendMessage(connectionId, input) {
2085
+ return this.http.post("/integrations/communication/messages", { connectionId, ...input });
2086
+ }
2087
+ // Users
2088
+ async listUsers(connectionId, options) {
2089
+ const params = new URLSearchParams({ connectionId });
2090
+ if (options?.cursor) params.set("cursor", options.cursor);
2091
+ if (options?.limit) params.set("limit", String(options.limit));
2092
+ return this.http.get(`/integrations/communication/users?${params}`);
2093
+ }
2094
+ };
2095
+ var Productivity = class {
2096
+ http;
2097
+ constructor(http) {
2098
+ this.http = http;
2099
+ }
2100
+ // Documents
2101
+ async listDocuments(connectionId, parentId, options) {
2102
+ const params = new URLSearchParams({ connectionId });
2103
+ if (parentId) params.set("parentId", parentId);
2104
+ if (options?.cursor) params.set("cursor", options.cursor);
2105
+ if (options?.limit) params.set("limit", String(options.limit));
2106
+ return this.http.get(`/integrations/productivity/documents?${params}`);
2107
+ }
2108
+ async getDocument(connectionId, id) {
2109
+ return this.http.get(`/integrations/productivity/documents/${id}?connectionId=${connectionId}`);
2110
+ }
2111
+ async createDocument(connectionId, data) {
2112
+ return this.http.post("/integrations/productivity/documents", { connectionId, ...data });
2113
+ }
2114
+ async updateDocument(connectionId, id, data) {
2115
+ return this.http.patch(`/integrations/productivity/documents/${id}`, { connectionId, ...data });
2116
+ }
2117
+ // Tables
2118
+ async listTables(connectionId, options) {
2119
+ const params = new URLSearchParams({ connectionId });
2120
+ if (options?.cursor) params.set("cursor", options.cursor);
2121
+ if (options?.limit) params.set("limit", String(options.limit));
2122
+ return this.http.get(`/integrations/productivity/tables?${params}`);
2123
+ }
2124
+ async getTable(connectionId, id) {
2125
+ return this.http.get(`/integrations/productivity/tables/${id}?connectionId=${connectionId}`);
2126
+ }
2127
+ // Table Rows
2128
+ async listTableRows(connectionId, tableId, options) {
2129
+ const params = new URLSearchParams({ connectionId });
2130
+ if (options?.cursor) params.set("cursor", options.cursor);
2131
+ if (options?.limit) params.set("limit", String(options.limit));
2132
+ return this.http.get(`/integrations/productivity/tables/${tableId}/rows?${params}`);
2133
+ }
2134
+ async getTableRow(connectionId, tableId, rowId) {
2135
+ return this.http.get(
2136
+ `/integrations/productivity/tables/${tableId}/rows/${rowId}?connectionId=${connectionId}`
2137
+ );
2138
+ }
2139
+ async createTableRow(connectionId, tableId, data) {
2140
+ return this.http.post(`/integrations/productivity/tables/${tableId}/rows`, {
2141
+ connectionId,
2142
+ ...data
2143
+ });
2144
+ }
2145
+ async updateTableRow(connectionId, tableId, rowId, data) {
2146
+ return this.http.patch(`/integrations/productivity/tables/${tableId}/rows/${rowId}`, {
2147
+ connectionId,
2148
+ ...data
2149
+ });
2150
+ }
2151
+ async deleteTableRow(connectionId, tableId, rowId) {
2152
+ return this.http.delete(
2153
+ `/integrations/productivity/tables/${tableId}/rows/${rowId}?connectionId=${connectionId}`
2154
+ );
2155
+ }
2156
+ };
2157
+ var Integrations = class {
2158
+ http;
2159
+ crm;
2160
+ storage;
2161
+ communication;
2162
+ productivity;
2163
+ constructor(config) {
2164
+ this.http = new HttpClient(config);
2165
+ this.crm = new CRM(this.http);
2166
+ this.storage = new Storage(this.http);
2167
+ this.communication = new Communication(this.http);
2168
+ this.productivity = new Productivity(this.http);
2169
+ }
2170
+ // ============================================================================
2171
+ // CONNECTORS
2172
+ // ============================================================================
2173
+ /**
2174
+ * List all available connectors
2175
+ */
2176
+ async listConnectors(category) {
2177
+ const params = category ? `?category=${category}` : "";
2178
+ return this.http.get(`/integrations/connectors${params}`);
2179
+ }
2180
+ /**
2181
+ * Get a specific connector
2182
+ */
2183
+ async getConnector(slug) {
2184
+ return this.http.get(`/integrations/connectors/${slug}`);
2185
+ }
2186
+ // ============================================================================
2187
+ // CONNECTIONS
2188
+ // ============================================================================
2189
+ /**
2190
+ * List all connections
2191
+ */
2192
+ async listConnections(options) {
2193
+ const params = new URLSearchParams();
2194
+ if (options?.connectorId) params.set("connectorId", options.connectorId);
2195
+ if (options?.status) params.set("status", options.status);
2196
+ const queryString = params.toString();
2197
+ return this.http.get(`/integrations/connections${queryString ? `?${queryString}` : ""}`);
2198
+ }
2199
+ /**
2200
+ * Get a specific connection
2201
+ */
2202
+ async getConnection(id) {
2203
+ return this.http.get(`/integrations/connections/${id}`);
2204
+ }
2205
+ /**
2206
+ * Create a new connection (initiates OAuth flow)
2207
+ * Returns the OAuth authorization URL to redirect the user to
2208
+ */
2209
+ async createConnection(connectorSlug, options) {
2210
+ return this.http.post("/integrations/connections", {
2211
+ connectorSlug,
2212
+ ...options
2213
+ });
2214
+ }
2215
+ /**
2216
+ * Delete a connection
2217
+ */
2218
+ async deleteConnection(id) {
2219
+ return this.http.delete(`/integrations/connections/${id}`);
2220
+ }
2221
+ /**
2222
+ * Test a connection's credentials
2223
+ */
2224
+ async testConnection(id) {
2225
+ return this.http.post(`/integrations/connections/${id}/test`, {});
2226
+ }
2227
+ // ============================================================================
2228
+ // PASSTHROUGH
2229
+ // ============================================================================
2230
+ /**
2231
+ * Make a raw passthrough request to the provider API
2232
+ */
2233
+ async passthrough(request) {
2234
+ return this.http.post("/integrations/passthrough", request);
2235
+ }
2236
+ };
2237
+
2238
+ // src/marketing/client.ts
2239
+ var Marketing = class {
2240
+ http;
2241
+ constructor(config) {
2242
+ this.http = new HttpClient(config);
2243
+ }
2244
+ // ============================================================================
2245
+ // Trends
2246
+ // ============================================================================
2247
+ /**
2248
+ * Discover new trends from all sources
2249
+ *
2250
+ * @example
2251
+ * ```typescript
2252
+ * const { trendsDiscovered, trends } = await marketing.discoverTrends({
2253
+ * projectSlug: 'my-project',
2254
+ * environment: 'production',
2255
+ * });
2256
+ * console.log(`Discovered ${trendsDiscovered} new trends`);
2257
+ * ```
2258
+ */
2259
+ async discoverTrends(request) {
2260
+ return this.http.post("/marketing/trends/discover", request);
2261
+ }
2262
+ /**
2263
+ * List trends for a project
2264
+ *
2265
+ * @example
2266
+ * ```typescript
2267
+ * const trends = await marketing.listTrends({
2268
+ * projectSlug: 'my-project',
2269
+ * environment: 'production',
2270
+ * limit: 20,
2271
+ * });
2272
+ * ```
2273
+ */
2274
+ async listTrends(request) {
2275
+ return this.http.get(
2276
+ `/marketing/trends?${new URLSearchParams({
2277
+ projectSlug: request.projectSlug,
2278
+ environment: request.environment,
2279
+ ...request.status && { status: request.status },
2280
+ ...request.limit && { limit: request.limit.toString() }
2281
+ }).toString()}`
2282
+ );
2283
+ }
2284
+ /**
2285
+ * Get a single trend by ID
2286
+ */
2287
+ async getTrend(trendId) {
2288
+ const response = await this.http.get(`/marketing/trends/${trendId}`);
2289
+ return this.convertTrendDates(response);
2290
+ }
2291
+ // ============================================================================
2292
+ // Opportunities
2293
+ // ============================================================================
2294
+ /**
2295
+ * Generate content opportunities from active trends
2296
+ *
2297
+ * @example
2298
+ * ```typescript
2299
+ * const { opportunitiesGenerated, opportunities } = await marketing.generateOpportunities({
2300
+ * projectSlug: 'my-project',
2301
+ * environment: 'production',
2302
+ * });
2303
+ * console.log(`Generated ${opportunitiesGenerated} new content ideas`);
2304
+ * ```
2305
+ */
2306
+ async generateOpportunities(request) {
2307
+ return this.http.post("/marketing/opportunities/generate", request);
2308
+ }
2309
+ /**
2310
+ * List opportunities for a project
2311
+ *
2312
+ * @example
2313
+ * ```typescript
2314
+ * const opportunities = await marketing.listOpportunities({
2315
+ * projectSlug: 'my-project',
2316
+ * environment: 'production',
2317
+ * status: 'pending',
2318
+ * limit: 20,
2319
+ * });
2320
+ * ```
2321
+ */
2322
+ async listOpportunities(request) {
2323
+ const params = new URLSearchParams({
2324
+ projectSlug: request.projectSlug,
2325
+ environment: request.environment,
2326
+ ...request.status && { status: request.status },
2327
+ ...request.limit && { limit: request.limit.toString() }
2328
+ });
2329
+ return this.http.get(`/marketing/opportunities?${params.toString()}`);
2330
+ }
2331
+ /**
2332
+ * Get a single opportunity by ID
2333
+ */
2334
+ async getOpportunity(opportunityId) {
2335
+ const response = await this.http.get(`/marketing/opportunities/${opportunityId}`);
2336
+ return this.convertOpportunityDates(response);
2337
+ }
2338
+ /**
2339
+ * Dismiss an opportunity
2340
+ *
2341
+ * @example
2342
+ * ```typescript
2343
+ * await marketing.dismissOpportunity({ opportunityId: 'opp-id' });
2344
+ * ```
2345
+ */
2346
+ async dismissOpportunity(request) {
2347
+ return this.http.post(`/marketing/opportunities/${request.opportunityId}/dismiss`, {});
2348
+ }
2349
+ // ============================================================================
2350
+ // Content
2351
+ // ============================================================================
2352
+ /**
2353
+ * Create new marketing content
2354
+ *
2355
+ * @example
2356
+ * ```typescript
2357
+ * const content = await marketing.createContent({
2358
+ * projectSlug: 'my-project',
2359
+ * environment: 'production',
2360
+ * contentType: 'tiktok_slideshow',
2361
+ * title: 'How AI is Changing Marketing',
2362
+ * opportunityId: 'opp-id',
2363
+ * });
2364
+ * ```
2365
+ */
2366
+ async createContent(request) {
2367
+ const response = await this.http.post("/marketing/content", request);
2368
+ return this.convertContentDates(response);
2369
+ }
2370
+ /**
2371
+ * List content with filters
2372
+ *
2373
+ * @example
2374
+ * ```typescript
2375
+ * const content = await marketing.listContent({
2376
+ * projectSlug: 'my-project',
2377
+ * environment: 'production',
2378
+ * status: 'published',
2379
+ * limit: 20,
2380
+ * });
2381
+ * ```
2382
+ */
2383
+ async listContent(request) {
2384
+ const params = new URLSearchParams({
2385
+ projectSlug: request.projectSlug,
2386
+ environment: request.environment,
2387
+ ...request.status && { status: request.status },
2388
+ ...request.contentType && { contentType: request.contentType },
2389
+ ...request.approvalStatus && { approvalStatus: request.approvalStatus },
2390
+ ...request.limit && { limit: request.limit.toString() },
2391
+ ...request.offset && { offset: request.offset.toString() }
2392
+ });
2393
+ const response = await this.http.get(`/marketing/content?${params.toString()}`);
2394
+ return response.map((c) => this.convertContentDates(c));
2395
+ }
2396
+ /**
2397
+ * Get a single content by ID
2398
+ */
2399
+ async getContent(contentId) {
2400
+ const response = await this.http.get(`/marketing/content/${contentId}`);
2401
+ return this.convertContentDates(response);
2402
+ }
2403
+ /**
2404
+ * Update content
2405
+ *
2406
+ * @example
2407
+ * ```typescript
2408
+ * const updated = await marketing.updateContent({
2409
+ * contentId: 'content-id',
2410
+ * title: 'Updated Title',
2411
+ * status: 'published',
2412
+ * });
2413
+ * ```
2414
+ */
2415
+ async updateContent(request) {
2416
+ const { contentId, ...data } = request;
2417
+ const response = await this.http.patch(`/marketing/content/${contentId}`, data);
2418
+ return this.convertContentDates(response);
2419
+ }
2420
+ /**
2421
+ * Approve content for publishing
2422
+ *
2423
+ * @example
2424
+ * ```typescript
2425
+ * await marketing.approveContent({
2426
+ * contentId: 'content-id',
2427
+ * reviewNotes: 'Looks great!',
2428
+ * });
2429
+ * ```
2430
+ */
2431
+ async approveContent(request) {
2432
+ const response = await this.http.post(`/marketing/content/${request.contentId}/approve`, request);
2433
+ return this.convertContentDates(response);
2434
+ }
2435
+ /**
2436
+ * Reject content
2437
+ *
2438
+ * @example
2439
+ * ```typescript
2440
+ * await marketing.rejectContent({
2441
+ * contentId: 'content-id',
2442
+ * reviewNotes: 'Needs revisions',
2443
+ * });
2444
+ * ```
2445
+ */
2446
+ async rejectContent(request) {
2447
+ const response = await this.http.post(`/marketing/content/${request.contentId}/reject`, request);
2448
+ return this.convertContentDates(response);
2449
+ }
2450
+ /**
2451
+ * Delete content
2452
+ */
2453
+ async deleteContent(contentId) {
2454
+ return this.http.deleteWithBody(`/marketing/content/${contentId}`, { contentId });
2455
+ }
2456
+ // ============================================================================
2457
+ // Scripts
2458
+ // ============================================================================
2459
+ /**
2460
+ * Create a new script
2461
+ *
2462
+ * @example
2463
+ * ```typescript
2464
+ * const script = await marketing.createScript({
2465
+ * projectSlug: 'my-project',
2466
+ * environment: 'production',
2467
+ * hook: 'Are you ready to see the future?',
2468
+ * slides: [
2469
+ * { order: 0, text: 'AI is changing everything', voiceoverText: 'AI is transforming how we work', duration: 3 },
2470
+ * ],
2471
+ * cta: 'Follow for more insights!',
2472
+ * });
2473
+ * ```
2474
+ */
2475
+ async createScript(request) {
2476
+ const response = await this.http.post("/marketing/scripts", request);
2477
+ return this.convertScriptDates(response);
2478
+ }
2479
+ /**
2480
+ * List scripts
2481
+ */
2482
+ async listScripts(request) {
2483
+ const params = new URLSearchParams({
2484
+ projectSlug: request.projectSlug,
2485
+ environment: request.environment,
2486
+ ...request.contentId && { contentId: request.contentId },
2487
+ ...request.limit && { limit: request.limit.toString() }
2488
+ });
2489
+ const response = await this.http.get(`/marketing/scripts?${params.toString()}`);
2490
+ return response.map((s) => this.convertScriptDates(s));
2491
+ }
2492
+ /**
2493
+ * Get a single script by ID
2494
+ */
2495
+ async getScript(scriptId) {
2496
+ const response = await this.http.get(`/marketing/scripts/${scriptId}`);
2497
+ return this.convertScriptDates(response);
2498
+ }
2499
+ // ============================================================================
2500
+ // Analytics
2501
+ // ============================================================================
2502
+ /**
2503
+ * Get analytics overview
2504
+ *
2505
+ * @example
2506
+ * ```typescript
2507
+ * const analytics = await marketing.getAnalyticsOverview({
2508
+ * projectSlug: 'my-project',
2509
+ * environment: 'production',
2510
+ * });
2511
+ * console.log(`Total content: ${analytics.totalContent}`);
2512
+ * console.log(`Total views: ${analytics.engagement.views}`);
2513
+ * ```
2514
+ */
2515
+ async getAnalyticsOverview(request) {
2516
+ const params = new URLSearchParams({
2517
+ projectSlug: request.projectSlug,
2518
+ environment: request.environment,
2519
+ ...request.startDate && { startDate: request.startDate.toISOString() },
2520
+ ...request.endDate && { endDate: request.endDate.toISOString() }
2521
+ });
2522
+ return this.http.get(`/marketing/analytics/overview?${params.toString()}`);
2523
+ }
2524
+ /**
2525
+ * Get content performance metrics
2526
+ *
2527
+ * @example
2528
+ * ```typescript
2529
+ * const topContent = await marketing.getContentPerformance({
2530
+ * projectSlug: 'my-project',
2531
+ * environment: 'production',
2532
+ * contentType: 'tiktok_slideshow',
2533
+ * limit: 10,
2534
+ * });
2535
+ * ```
2536
+ */
2537
+ async getContentPerformance(request) {
2538
+ const params = new URLSearchParams({
2539
+ projectSlug: request.projectSlug,
2540
+ environment: request.environment,
2541
+ ...request.contentType && { contentType: request.contentType },
2542
+ ...request.limit && { limit: request.limit.toString() }
2543
+ });
2544
+ return this.http.get(`/marketing/analytics/performance?${params.toString()}`);
2545
+ }
2546
+ // ============================================================================
2547
+ // Date Conversion Helpers
2548
+ // ============================================================================
2549
+ convertTrendDates(trend) {
2550
+ if (typeof trend.firstSeenAt === "string") {
2551
+ trend.firstSeenAt = new Date(trend.firstSeenAt);
2552
+ }
2553
+ if (typeof trend.lastUpdatedAt === "string") {
2554
+ trend.lastUpdatedAt = new Date(trend.lastUpdatedAt);
2555
+ }
2556
+ if (trend.expiresAt && typeof trend.expiresAt === "string") {
2557
+ trend.expiresAt = new Date(trend.expiresAt);
2558
+ }
2559
+ if (typeof trend.createdAt === "string") {
2560
+ trend.createdAt = new Date(trend.createdAt);
2561
+ }
2562
+ return trend;
2563
+ }
2564
+ convertOpportunityDates(opp) {
2565
+ if (typeof opp.createdAt === "string") {
2566
+ opp.createdAt = new Date(opp.createdAt);
2567
+ }
2568
+ if (opp.expiresAt && typeof opp.expiresAt === "string") {
2569
+ opp.expiresAt = new Date(opp.expiresAt);
2570
+ }
2571
+ if (opp.usedAt && typeof opp.usedAt === "string") {
2572
+ opp.usedAt = new Date(opp.usedAt);
2573
+ }
2574
+ return opp;
2575
+ }
2576
+ convertContentDates(content) {
2577
+ if (typeof content.createdAt === "string") {
2578
+ content.createdAt = new Date(content.createdAt);
2579
+ }
2580
+ if (content.updatedAt && typeof content.updatedAt === "string") {
2581
+ content.updatedAt = new Date(content.updatedAt);
2582
+ }
2583
+ if (content.reviewedAt && typeof content.reviewedAt === "string") {
2584
+ content.reviewedAt = new Date(content.reviewedAt);
2585
+ }
2586
+ if (content.publishedAt && typeof content.publishedAt === "string") {
2587
+ content.publishedAt = new Date(content.publishedAt);
2588
+ }
2589
+ return content;
2590
+ }
2591
+ convertScriptDates(script) {
2592
+ if (typeof script.createdAt === "string") {
2593
+ script.createdAt = new Date(script.createdAt);
2594
+ }
2595
+ return script;
2596
+ }
2597
+ };
2598
+
1716
2599
  // src/index.ts
1717
2600
  var Stack0 = class {
1718
2601
  mail;
1719
2602
  cdn;
1720
2603
  screenshots;
1721
2604
  extraction;
2605
+ integrations;
2606
+ marketing;
1722
2607
  /**
1723
2608
  * @deprecated Use `screenshots` and `extraction` instead. Will be removed in a future version.
1724
2609
  */
@@ -1729,14 +2614,16 @@ var Stack0 = class {
1729
2614
  baseUrl: config.baseUrl
1730
2615
  };
1731
2616
  this.mail = new Mail(clientConfig);
1732
- this.cdn = new CDN(clientConfig);
2617
+ this.cdn = new CDN(clientConfig, config.cdnUrl);
1733
2618
  this.screenshots = new Screenshots(clientConfig);
1734
2619
  this.extraction = new Extraction(clientConfig);
2620
+ this.integrations = new Integrations(clientConfig);
2621
+ this.marketing = new Marketing(clientConfig);
1735
2622
  this.webdata = new Webdata(clientConfig);
1736
2623
  }
1737
2624
  };
1738
2625
  var src_default = Stack0;
1739
2626
 
1740
- export { CDN, Extraction, Mail, Screenshots, Stack0, Webdata, src_default as default };
2627
+ export { CDN, Extraction, Integrations, Mail, Marketing, Screenshots, Stack0, Webdata, src_default as default };
1741
2628
  //# sourceMappingURL=index.mjs.map
1742
2629
  //# sourceMappingURL=index.mjs.map