@stack0/sdk 0.3.0 → 0.3.4

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 (40) hide show
  1. package/README.md +33 -10
  2. package/dist/cdn/index.d.mts +56 -26
  3. package/dist/cdn/index.d.ts +56 -26
  4. package/dist/cdn/index.js +84 -23
  5. package/dist/cdn/index.js.map +1 -1
  6. package/dist/cdn/index.mjs +84 -23
  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-DjrRWvXA.d.mts → http-client-Cgie_Rv6.d.mts} +1 -0
  15. package/dist/{http-client-DjrRWvXA.d.ts → http-client-Cgie_Rv6.d.ts} +1 -0
  16. package/dist/index.d.mts +475 -3
  17. package/dist/index.d.ts +475 -3
  18. package/dist/index.js +512 -72
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs +512 -73
  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 -2
package/README.md CHANGED
@@ -50,6 +50,7 @@ import { Stack0 } from '@stack0/sdk';
50
50
  const stack0 = new Stack0({
51
51
  apiKey: 'stack0_...', // Required: Your API key
52
52
  baseUrl: 'https://api.stack0.dev/v1', // Optional: Custom API endpoint
53
+ cdnUrl: 'https://cdn.yourproject.stack0.dev', // Optional: For client-side image transforms
53
54
  });
54
55
  ```
55
56
 
@@ -169,24 +170,46 @@ await stack0.cdn.move({
169
170
 
170
171
  ### Image Transformations
171
172
 
172
- Get optimized and transformed image URLs:
173
+ Generate optimized and transformed image URLs client-side (no API call):
173
174
 
174
175
  ```typescript
175
- const { url } = await stack0.cdn.getTransformUrl({
176
- assetId: 'asset-id',
177
- options: {
178
- width: 800,
179
- height: 600,
180
- fit: 'cover', // 'cover', 'contain', 'fill', 'inside', 'outside'
181
- format: 'webp', // 'webp', 'jpeg', 'png', 'avif'
182
- quality: 80,
183
- },
176
+ // Using asset's cdnUrl directly (recommended)
177
+ const url = stack0.cdn.getTransformUrl(asset.cdnUrl, {
178
+ width: 800,
179
+ height: 600,
180
+ fit: 'cover', // 'cover', 'contain', 'fill', 'inside', 'outside'
181
+ format: 'webp', // 'webp', 'jpeg', 'png', 'avif', 'auto'
182
+ quality: 80,
184
183
  });
185
184
 
185
+ // Or using s3Key when cdnUrl is configured in Stack0 options
186
+ const url = stack0.cdn.getTransformUrl(asset.s3Key, { width: 400 });
187
+
186
188
  // Use in <img> tag
187
189
  // <img src={url} alt="Optimized image" />
188
190
  ```
189
191
 
192
+ Advanced transform options:
193
+
194
+ ```typescript
195
+ const url = stack0.cdn.getTransformUrl(asset.cdnUrl, {
196
+ width: 800,
197
+ height: 600,
198
+ fit: 'cover',
199
+ format: 'webp',
200
+ quality: 80,
201
+ crop: 'attention', // Smart crop: 'attention', 'entropy', 'center', etc.
202
+ blur: 5, // Blur sigma (0.3-100)
203
+ sharpen: 1.5, // Sharpen sigma
204
+ brightness: 10, // -100 to 100
205
+ saturation: -50, // -100 to 100
206
+ grayscale: true, // Convert to grayscale
207
+ rotate: 90, // 0, 90, 180, 270
208
+ flip: true, // Flip vertically
209
+ flop: true, // Flip horizontally
210
+ });
211
+ ```
212
+
190
213
  ### Folders
191
214
 
192
215
  ```typescript
@@ -1,4 +1,4 @@
1
- import { a as HttpClientConfig } from '../http-client-DjrRWvXA.mjs';
1
+ import { a as HttpClientConfig } from '../http-client-Cgie_Rv6.mjs';
2
2
 
3
3
  /**
4
4
  * Type definitions for Stack0 CDN API
@@ -92,22 +92,42 @@ interface MoveAssetsResponse {
92
92
  movedCount: number;
93
93
  }
94
94
  interface TransformOptions {
95
+ /** Output width (snapped to nearest allowed width for caching) */
95
96
  width?: number;
97
+ /** Output height */
96
98
  height?: number;
99
+ /** Resize fit mode */
97
100
  fit?: "cover" | "contain" | "fill" | "inside" | "outside";
98
- format?: "webp" | "jpeg" | "png" | "avif";
101
+ /** Output format */
102
+ format?: "webp" | "jpeg" | "png" | "avif" | "auto";
103
+ /** Quality 1-100 */
99
104
  quality?: number;
100
- }
101
- interface GetTransformUrlRequest {
102
- assetId: string;
103
- options: TransformOptions;
104
- }
105
- interface GetTransformUrlResponse {
106
- url: string;
107
- originalUrl: string;
108
- width?: number;
109
- height?: number;
110
- format?: string;
105
+ /** Smart crop position */
106
+ crop?: "attention" | "entropy" | "center" | "top" | "bottom" | "left" | "right";
107
+ /** Manual crop X offset */
108
+ cropX?: number;
109
+ /** Manual crop Y offset */
110
+ cropY?: number;
111
+ /** Manual crop width */
112
+ cropWidth?: number;
113
+ /** Manual crop height */
114
+ cropHeight?: number;
115
+ /** Blur sigma (0.3-100) */
116
+ blur?: number;
117
+ /** Sharpen sigma */
118
+ sharpen?: number;
119
+ /** Brightness adjustment (-100 to 100) */
120
+ brightness?: number;
121
+ /** Saturation adjustment (-100 to 100) */
122
+ saturation?: number;
123
+ /** Convert to grayscale */
124
+ grayscale?: boolean;
125
+ /** Rotation angle (0, 90, 180, 270) */
126
+ rotate?: number;
127
+ /** Flip vertically */
128
+ flip?: boolean;
129
+ /** Flop horizontally */
130
+ flop?: boolean;
111
131
  }
112
132
  interface FolderTreeNode {
113
133
  id: string;
@@ -232,7 +252,8 @@ interface ExtractAudioResponse {
232
252
 
233
253
  declare class CDN {
234
254
  private http;
235
- constructor(config: HttpClientConfig);
255
+ private cdnUrl?;
256
+ constructor(config: HttpClientConfig, cdnUrl?: string);
236
257
  /**
237
258
  * Generate a presigned URL for uploading a file
238
259
  *
@@ -352,23 +373,32 @@ declare class CDN {
352
373
  */
353
374
  move(request: MoveAssetsRequest): Promise<MoveAssetsResponse>;
354
375
  /**
355
- * Get a transformed image URL
376
+ * Get a transformed image URL (client-side, no API call)
356
377
  *
357
378
  * @example
358
379
  * ```typescript
359
- * const { url } = await cdn.getTransformUrl({
360
- * assetId: 'asset-id',
361
- * options: {
362
- * width: 800,
363
- * height: 600,
364
- * fit: 'cover',
365
- * format: 'webp',
366
- * quality: 80,
367
- * },
380
+ * // Using asset's cdnUrl directly
381
+ * const url = cdn.getTransformUrl(asset.cdnUrl, {
382
+ * width: 800,
383
+ * height: 600,
384
+ * fit: 'cover',
385
+ * format: 'webp',
386
+ * quality: 80,
368
387
  * });
388
+ *
389
+ * // Or using cdnUrl from SDK config + s3Key
390
+ * const url = cdn.getTransformUrl(asset.s3Key, { width: 400 });
369
391
  * ```
370
392
  */
371
- getTransformUrl(request: GetTransformUrlRequest): Promise<GetTransformUrlResponse>;
393
+ getTransformUrl(assetUrlOrS3Key: string, options: TransformOptions): string;
394
+ /**
395
+ * Build transform query parameters
396
+ */
397
+ private buildTransformQuery;
398
+ /**
399
+ * Find the nearest allowed width for optimal caching
400
+ */
401
+ private getNearestWidth;
372
402
  /**
373
403
  * Get folder tree for navigation
374
404
  *
@@ -502,4 +532,4 @@ declare class CDN {
502
532
  private convertJobDates;
503
533
  }
504
534
 
505
- export { type Asset, type AssetStatus, type AssetType, CDN, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateFolderRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type ExtractAudioRequest, type ExtractAudioResponse, type Folder, type FolderTreeNode, type GetAssetRequest, type GetFolderTreeRequest, type GetTransformUrlRequest, type GetTransformUrlResponse, type ListAssetsRequest, type ListAssetsResponse, type ListJobsRequest, type ListJobsResponse, type MoveAssetsRequest, type MoveAssetsResponse, type StreamingUrls, type ThumbnailRequest, type ThumbnailResponse, type TranscodeJob, type TranscodeVideoRequest, type TranscodingStatus, type TransformOptions, type TrimOptions, type UpdateAssetRequest, type UploadUrlRequest, type UploadUrlResponse, type VideoCodec, type VideoOutputFormat, type VideoQuality, type VideoVariant, type WatermarkOptions };
535
+ export { type Asset, type AssetStatus, type AssetType, CDN, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateFolderRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type ExtractAudioRequest, type ExtractAudioResponse, type Folder, type FolderTreeNode, type GetAssetRequest, type GetFolderTreeRequest, type ListAssetsRequest, type ListAssetsResponse, type ListJobsRequest, type ListJobsResponse, type MoveAssetsRequest, type MoveAssetsResponse, type StreamingUrls, type ThumbnailRequest, type ThumbnailResponse, type TranscodeJob, type TranscodeVideoRequest, type TranscodingStatus, type TransformOptions, type TrimOptions, type UpdateAssetRequest, type UploadUrlRequest, type UploadUrlResponse, type VideoCodec, type VideoOutputFormat, type VideoQuality, type VideoVariant, type WatermarkOptions };
@@ -1,4 +1,4 @@
1
- import { a as HttpClientConfig } from '../http-client-DjrRWvXA.js';
1
+ import { a as HttpClientConfig } from '../http-client-Cgie_Rv6.js';
2
2
 
3
3
  /**
4
4
  * Type definitions for Stack0 CDN API
@@ -92,22 +92,42 @@ interface MoveAssetsResponse {
92
92
  movedCount: number;
93
93
  }
94
94
  interface TransformOptions {
95
+ /** Output width (snapped to nearest allowed width for caching) */
95
96
  width?: number;
97
+ /** Output height */
96
98
  height?: number;
99
+ /** Resize fit mode */
97
100
  fit?: "cover" | "contain" | "fill" | "inside" | "outside";
98
- format?: "webp" | "jpeg" | "png" | "avif";
101
+ /** Output format */
102
+ format?: "webp" | "jpeg" | "png" | "avif" | "auto";
103
+ /** Quality 1-100 */
99
104
  quality?: number;
100
- }
101
- interface GetTransformUrlRequest {
102
- assetId: string;
103
- options: TransformOptions;
104
- }
105
- interface GetTransformUrlResponse {
106
- url: string;
107
- originalUrl: string;
108
- width?: number;
109
- height?: number;
110
- format?: string;
105
+ /** Smart crop position */
106
+ crop?: "attention" | "entropy" | "center" | "top" | "bottom" | "left" | "right";
107
+ /** Manual crop X offset */
108
+ cropX?: number;
109
+ /** Manual crop Y offset */
110
+ cropY?: number;
111
+ /** Manual crop width */
112
+ cropWidth?: number;
113
+ /** Manual crop height */
114
+ cropHeight?: number;
115
+ /** Blur sigma (0.3-100) */
116
+ blur?: number;
117
+ /** Sharpen sigma */
118
+ sharpen?: number;
119
+ /** Brightness adjustment (-100 to 100) */
120
+ brightness?: number;
121
+ /** Saturation adjustment (-100 to 100) */
122
+ saturation?: number;
123
+ /** Convert to grayscale */
124
+ grayscale?: boolean;
125
+ /** Rotation angle (0, 90, 180, 270) */
126
+ rotate?: number;
127
+ /** Flip vertically */
128
+ flip?: boolean;
129
+ /** Flop horizontally */
130
+ flop?: boolean;
111
131
  }
112
132
  interface FolderTreeNode {
113
133
  id: string;
@@ -232,7 +252,8 @@ interface ExtractAudioResponse {
232
252
 
233
253
  declare class CDN {
234
254
  private http;
235
- constructor(config: HttpClientConfig);
255
+ private cdnUrl?;
256
+ constructor(config: HttpClientConfig, cdnUrl?: string);
236
257
  /**
237
258
  * Generate a presigned URL for uploading a file
238
259
  *
@@ -352,23 +373,32 @@ declare class CDN {
352
373
  */
353
374
  move(request: MoveAssetsRequest): Promise<MoveAssetsResponse>;
354
375
  /**
355
- * Get a transformed image URL
376
+ * Get a transformed image URL (client-side, no API call)
356
377
  *
357
378
  * @example
358
379
  * ```typescript
359
- * const { url } = await cdn.getTransformUrl({
360
- * assetId: 'asset-id',
361
- * options: {
362
- * width: 800,
363
- * height: 600,
364
- * fit: 'cover',
365
- * format: 'webp',
366
- * quality: 80,
367
- * },
380
+ * // Using asset's cdnUrl directly
381
+ * const url = cdn.getTransformUrl(asset.cdnUrl, {
382
+ * width: 800,
383
+ * height: 600,
384
+ * fit: 'cover',
385
+ * format: 'webp',
386
+ * quality: 80,
368
387
  * });
388
+ *
389
+ * // Or using cdnUrl from SDK config + s3Key
390
+ * const url = cdn.getTransformUrl(asset.s3Key, { width: 400 });
369
391
  * ```
370
392
  */
371
- getTransformUrl(request: GetTransformUrlRequest): Promise<GetTransformUrlResponse>;
393
+ getTransformUrl(assetUrlOrS3Key: string, options: TransformOptions): string;
394
+ /**
395
+ * Build transform query parameters
396
+ */
397
+ private buildTransformQuery;
398
+ /**
399
+ * Find the nearest allowed width for optimal caching
400
+ */
401
+ private getNearestWidth;
372
402
  /**
373
403
  * Get folder tree for navigation
374
404
  *
@@ -502,4 +532,4 @@ declare class CDN {
502
532
  private convertJobDates;
503
533
  }
504
534
 
505
- export { type Asset, type AssetStatus, type AssetType, CDN, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateFolderRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type ExtractAudioRequest, type ExtractAudioResponse, type Folder, type FolderTreeNode, type GetAssetRequest, type GetFolderTreeRequest, type GetTransformUrlRequest, type GetTransformUrlResponse, type ListAssetsRequest, type ListAssetsResponse, type ListJobsRequest, type ListJobsResponse, type MoveAssetsRequest, type MoveAssetsResponse, type StreamingUrls, type ThumbnailRequest, type ThumbnailResponse, type TranscodeJob, type TranscodeVideoRequest, type TranscodingStatus, type TransformOptions, type TrimOptions, type UpdateAssetRequest, type UploadUrlRequest, type UploadUrlResponse, type VideoCodec, type VideoOutputFormat, type VideoQuality, type VideoVariant, type WatermarkOptions };
535
+ export { type Asset, type AssetStatus, type AssetType, CDN, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateFolderRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type ExtractAudioRequest, type ExtractAudioResponse, type Folder, type FolderTreeNode, type GetAssetRequest, type GetFolderTreeRequest, type ListAssetsRequest, type ListAssetsResponse, type ListJobsRequest, type ListJobsResponse, type MoveAssetsRequest, type MoveAssetsResponse, type StreamingUrls, type ThumbnailRequest, type ThumbnailResponse, type TranscodeJob, type TranscodeVideoRequest, type TranscodingStatus, type TransformOptions, type TrimOptions, type UpdateAssetRequest, type UploadUrlRequest, type UploadUrlResponse, type VideoCodec, type VideoOutputFormat, type VideoQuality, type VideoVariant, type WatermarkOptions };
package/dist/cdn/index.js CHANGED
@@ -8,19 +8,24 @@ var HttpClient = class {
8
8
  this.apiKey = config.apiKey;
9
9
  this.baseUrl = config.baseUrl || "https://api.stack0.dev/v1";
10
10
  }
11
- getHeaders() {
12
- return {
13
- "Content-Type": "application/json",
11
+ getHeaders(includeContentType = true) {
12
+ const headers = {
14
13
  Authorization: `Bearer ${this.apiKey}`
15
14
  };
15
+ if (includeContentType) {
16
+ headers["Content-Type"] = "application/json";
17
+ }
18
+ return headers;
16
19
  }
17
20
  async request(method, path, body) {
18
21
  const url = `${this.baseUrl}${path}`;
22
+ const bodyString = body === void 0 ? void 0 : JSON.stringify(body);
23
+ const hasBody = bodyString !== void 0;
19
24
  try {
20
25
  const response = await fetch(url, {
21
26
  method,
22
- headers: this.getHeaders(),
23
- body: body ? JSON.stringify(body) : void 0
27
+ headers: this.getHeaders(hasBody),
28
+ body: hasBody ? bodyString : void 0
24
29
  });
25
30
  if (!response.ok) {
26
31
  await this.handleErrorResponse(response);
@@ -64,16 +69,22 @@ var HttpClient = class {
64
69
  async delete(path) {
65
70
  return this.request("DELETE", path);
66
71
  }
72
+ async deleteWithBody(path, body) {
73
+ return this.request("DELETE", path, body);
74
+ }
67
75
  async patch(path, body) {
68
76
  return this.request("PATCH", path, body);
69
77
  }
70
78
  };
71
79
 
72
80
  // src/cdn/client.ts
81
+ var ALLOWED_WIDTHS = [256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840];
73
82
  var CDN = class {
74
83
  http;
75
- constructor(config) {
84
+ cdnUrl;
85
+ constructor(config, cdnUrl) {
76
86
  this.http = new HttpClient(config);
87
+ this.cdnUrl = cdnUrl;
77
88
  }
78
89
  /**
79
90
  * Generate a presigned URL for uploading a file
@@ -194,7 +205,7 @@ var CDN = class {
194
205
  * ```
195
206
  */
196
207
  async delete(id) {
197
- return this.http.delete(`/cdn/assets/${id}`);
208
+ return this.http.deleteWithBody(`/cdn/assets/${id}`, { id });
198
209
  }
199
210
  /**
200
211
  * Delete multiple assets
@@ -253,24 +264,73 @@ var CDN = class {
253
264
  return this.http.post("/cdn/assets/move", request);
254
265
  }
255
266
  /**
256
- * Get a transformed image URL
267
+ * Get a transformed image URL (client-side, no API call)
257
268
  *
258
269
  * @example
259
270
  * ```typescript
260
- * const { url } = await cdn.getTransformUrl({
261
- * assetId: 'asset-id',
262
- * options: {
263
- * width: 800,
264
- * height: 600,
265
- * fit: 'cover',
266
- * format: 'webp',
267
- * quality: 80,
268
- * },
271
+ * // Using asset's cdnUrl directly
272
+ * const url = cdn.getTransformUrl(asset.cdnUrl, {
273
+ * width: 800,
274
+ * height: 600,
275
+ * fit: 'cover',
276
+ * format: 'webp',
277
+ * quality: 80,
269
278
  * });
279
+ *
280
+ * // Or using cdnUrl from SDK config + s3Key
281
+ * const url = cdn.getTransformUrl(asset.s3Key, { width: 400 });
270
282
  * ```
271
283
  */
272
- async getTransformUrl(request) {
273
- return this.http.post("/cdn/transform", request);
284
+ getTransformUrl(assetUrlOrS3Key, options) {
285
+ let baseUrl;
286
+ if (assetUrlOrS3Key.startsWith("http://") || assetUrlOrS3Key.startsWith("https://")) {
287
+ const url = new URL(assetUrlOrS3Key);
288
+ baseUrl = `${url.protocol}//${url.host}${url.pathname}`;
289
+ } else if (this.cdnUrl) {
290
+ const cdnBase = this.cdnUrl.endsWith("/") ? this.cdnUrl.slice(0, -1) : this.cdnUrl;
291
+ baseUrl = `${cdnBase}/${assetUrlOrS3Key}`;
292
+ } else {
293
+ throw new Error("getTransformUrl requires either a full URL or cdnUrl to be configured in Stack0 options");
294
+ }
295
+ const params = this.buildTransformQuery(options);
296
+ if (!params) {
297
+ return baseUrl;
298
+ }
299
+ return `${baseUrl}?${params}`;
300
+ }
301
+ /**
302
+ * Build transform query parameters
303
+ */
304
+ buildTransformQuery(options) {
305
+ const params = new URLSearchParams();
306
+ if (options.format) params.set("f", options.format);
307
+ if (options.quality !== void 0) params.set("q", options.quality.toString());
308
+ if (options.width !== void 0) {
309
+ const width = this.getNearestWidth(options.width);
310
+ params.set("w", width.toString());
311
+ }
312
+ if (options.height !== void 0) params.set("h", options.height.toString());
313
+ if (options.fit) params.set("fit", options.fit);
314
+ if (options.crop) params.set("crop", options.crop);
315
+ if (options.cropX !== void 0) params.set("crop-x", options.cropX.toString());
316
+ if (options.cropY !== void 0) params.set("crop-y", options.cropY.toString());
317
+ if (options.cropWidth !== void 0) params.set("crop-w", options.cropWidth.toString());
318
+ if (options.cropHeight !== void 0) params.set("crop-h", options.cropHeight.toString());
319
+ if (options.blur !== void 0) params.set("blur", options.blur.toString());
320
+ if (options.sharpen !== void 0) params.set("sharpen", options.sharpen.toString());
321
+ if (options.brightness !== void 0) params.set("brightness", options.brightness.toString());
322
+ if (options.saturation !== void 0) params.set("saturation", options.saturation.toString());
323
+ if (options.grayscale) params.set("grayscale", "true");
324
+ if (options.rotate !== void 0) params.set("rotate", options.rotate.toString());
325
+ if (options.flip) params.set("flip", "y");
326
+ if (options.flop) params.set("flop", "x");
327
+ return params.toString();
328
+ }
329
+ /**
330
+ * Find the nearest allowed width for optimal caching
331
+ */
332
+ getNearestWidth(width) {
333
+ return ALLOWED_WIDTHS.reduce((prev, curr) => Math.abs(curr - width) < Math.abs(prev - width) ? curr : prev);
274
334
  }
275
335
  /**
276
336
  * Get folder tree for navigation
@@ -316,7 +376,10 @@ var CDN = class {
316
376
  async deleteFolder(id, deleteContents = false) {
317
377
  const params = new URLSearchParams();
318
378
  if (deleteContents) params.set("deleteContents", "true");
319
- return this.http.delete(`/cdn/folders/${id}?${params.toString()}`);
379
+ return this.http.deleteWithBody(`/cdn/folders/${id}?${params.toString()}`, {
380
+ id,
381
+ deleteContents
382
+ });
320
383
  }
321
384
  convertAssetDates(asset) {
322
385
  if (typeof asset.createdAt === "string") {
@@ -442,9 +505,7 @@ var CDN = class {
442
505
  params.set("timestamp", request.timestamp.toString());
443
506
  if (request.width) params.set("width", request.width.toString());
444
507
  if (request.format) params.set("format", request.format);
445
- return this.http.get(
446
- `/cdn/video/thumbnail/${request.assetId}?${params.toString()}`
447
- );
508
+ return this.http.get(`/cdn/video/thumbnail/${request.assetId}?${params.toString()}`);
448
509
  }
449
510
  /**
450
511
  * Extract audio from a video file
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/http-client.ts","../../src/cdn/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * HTTP client for Stack0 API\n * Handles authentication, request/response formatting, and error handling\n */\n\nexport interface HttpClientConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class HttpClient {\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: HttpClientConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || \"https://api.stack0.dev/v1\";\n }\n\n private getHeaders(): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n try {\n const response = await fetch(url, {\n method,\n headers: this.getHeaders(),\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n const data = await response.json();\n return data as T;\n } catch (error) {\n if (error instanceof Error && \"statusCode\" in error) {\n throw error; // Re-throw our custom errors\n }\n throw this.createError(\"Network error\", error);\n }\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let errorBody: { message: string } | undefined;\n try {\n errorBody = (await response.json()) as { message: string };\n } catch {\n errorBody = { message: response.statusText };\n }\n\n const error = new Error(errorBody?.message || `HTTP ${response.status}`) as Error & {\n statusCode: number;\n code: string;\n response: unknown;\n };\n error.statusCode = response.status;\n error.code = (errorBody as unknown as { code: string } | undefined)?.code ?? \"\";\n error.response = errorBody;\n throw error;\n }\n\n private createError(message: string, cause?: unknown): Error {\n const error = new Error(message) as Error & { cause: unknown };\n error.cause = cause;\n return error;\n }\n\n async get<T>(path: string): Promise<T> {\n return this.request<T>(\"GET\", path);\n }\n\n async post<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"POST\", path, body);\n }\n\n async put<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PUT\", path, body);\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>(\"DELETE\", path);\n }\n\n async patch<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PATCH\", path, body);\n }\n}\n","/**\n * Stack0 CDN Client\n * Upload, manage, and transform assets\n */\n\nimport { HttpClient, type HttpClientConfig } from \"../lib/http-client\";\nimport type {\n Asset,\n UploadUrlRequest,\n UploadUrlResponse,\n UpdateAssetRequest,\n DeleteAssetsResponse,\n ListAssetsRequest,\n ListAssetsResponse,\n MoveAssetsRequest,\n MoveAssetsResponse,\n GetTransformUrlRequest,\n GetTransformUrlResponse,\n GetFolderTreeRequest,\n FolderTreeNode,\n CreateFolderRequest,\n Folder,\n TranscodeVideoRequest,\n TranscodeJob,\n ListJobsRequest,\n ListJobsResponse,\n StreamingUrls,\n ThumbnailRequest,\n ThumbnailResponse,\n ExtractAudioRequest,\n ExtractAudioResponse,\n} from \"./types\";\n\nexport class CDN {\n private http: HttpClient;\n\n constructor(config: HttpClientConfig) {\n this.http = new HttpClient(config);\n }\n\n /**\n * Generate a presigned URL for uploading a file\n *\n * @example\n * ```typescript\n * const { uploadUrl, assetId } = await cdn.getUploadUrl({\n * projectSlug: 'my-project',\n * filename: 'image.jpg',\n * mimeType: 'image/jpeg',\n * size: 1024 * 1024,\n * });\n *\n * // Upload file to the presigned URL\n * await fetch(uploadUrl, {\n * method: 'PUT',\n * body: file,\n * headers: { 'Content-Type': 'image/jpeg' },\n * });\n *\n * // Confirm the upload\n * const asset = await cdn.confirmUpload(assetId);\n * ```\n */\n async getUploadUrl(request: UploadUrlRequest): Promise<UploadUrlResponse> {\n const response = await this.http.post<UploadUrlResponse>(\"/cdn/upload\", request);\n\n if (typeof response.expiresAt === \"string\") {\n response.expiresAt = new Date(response.expiresAt);\n }\n\n return response;\n }\n\n /**\n * Confirm that an upload has completed\n */\n async confirmUpload(assetId: string): Promise<Asset> {\n const response = await this.http.post<Asset>(`/cdn/upload/${assetId}/confirm`, {});\n return this.convertAssetDates(response);\n }\n\n /**\n * Upload a file directly (handles presigned URL flow automatically)\n *\n * @example\n * ```typescript\n * const asset = await cdn.upload({\n * projectSlug: 'my-project',\n * file: fileBuffer,\n * filename: 'image.jpg',\n * mimeType: 'image/jpeg',\n * });\n * ```\n */\n async upload(options: {\n projectSlug: string;\n file: Blob | Buffer | ArrayBuffer;\n filename: string;\n mimeType: string;\n folder?: string;\n metadata?: Record<string, unknown>;\n }): Promise<Asset> {\n const { projectSlug, file, filename, mimeType, folder, metadata } = options;\n\n // Get file size\n let size: number;\n if (file instanceof Blob) {\n size = file.size;\n } else if (file instanceof ArrayBuffer) {\n size = file.byteLength;\n } else {\n // Buffer\n size = (file as Buffer).length;\n }\n\n // Get presigned URL\n const { uploadUrl, assetId } = await this.getUploadUrl({\n projectSlug,\n filename,\n mimeType,\n size,\n folder,\n metadata,\n });\n\n // Upload file\n const uploadResponse = await fetch(uploadUrl, {\n method: \"PUT\",\n body: file,\n headers: {\n \"Content-Type\": mimeType,\n },\n });\n\n if (!uploadResponse.ok) {\n throw new Error(`Upload failed: ${uploadResponse.statusText}`);\n }\n\n // Confirm upload\n return this.confirmUpload(assetId);\n }\n\n /**\n * Get an asset by ID\n *\n * @example\n * ```typescript\n * const asset = await cdn.get('asset-id');\n * console.log(asset.cdnUrl);\n * ```\n */\n async get(id: string): Promise<Asset> {\n const response = await this.http.get<Asset>(`/cdn/assets/${id}`);\n return this.convertAssetDates(response);\n }\n\n /**\n * Update asset metadata\n *\n * @example\n * ```typescript\n * const asset = await cdn.update({\n * id: 'asset-id',\n * alt: 'A beautiful sunset',\n * tags: ['nature', 'sunset'],\n * });\n * ```\n */\n async update(request: UpdateAssetRequest): Promise<Asset> {\n const { id, ...data } = request;\n const response = await this.http.patch<Asset>(`/cdn/assets/${id}`, data);\n return this.convertAssetDates(response);\n }\n\n /**\n * Delete an asset\n *\n * @example\n * ```typescript\n * await cdn.delete('asset-id');\n * ```\n */\n async delete(id: string): Promise<{ success: boolean }> {\n return this.http.delete<{ success: boolean }>(`/cdn/assets/${id}`);\n }\n\n /**\n * Delete multiple assets\n *\n * @example\n * ```typescript\n * const result = await cdn.deleteMany(['asset-1', 'asset-2']);\n * console.log(`Deleted ${result.deletedCount} assets`);\n * ```\n */\n async deleteMany(ids: string[]): Promise<DeleteAssetsResponse> {\n return this.http.post<DeleteAssetsResponse>(\"/cdn/assets/delete\", { ids });\n }\n\n /**\n * List assets with filters and pagination\n *\n * @example\n * ```typescript\n * const { assets, total, hasMore } = await cdn.list({\n * projectSlug: 'my-project',\n * type: 'image',\n * limit: 20,\n * });\n * ```\n */\n async list(request: ListAssetsRequest): Promise<ListAssetsResponse> {\n const params = new URLSearchParams();\n\n params.set(\"projectSlug\", request.projectSlug);\n if (request.folder !== undefined) params.set(\"folder\", request.folder ?? \"\");\n if (request.type) params.set(\"type\", request.type);\n if (request.status) params.set(\"status\", request.status);\n if (request.search) params.set(\"search\", request.search);\n if (request.tags) params.set(\"tags\", request.tags.join(\",\"));\n if (request.sortBy) params.set(\"sortBy\", request.sortBy);\n if (request.sortOrder) params.set(\"sortOrder\", request.sortOrder);\n if (request.limit) params.set(\"limit\", request.limit.toString());\n if (request.offset) params.set(\"offset\", request.offset.toString());\n\n const response = await this.http.get<ListAssetsResponse>(`/cdn/assets?${params.toString()}`);\n\n return {\n ...response,\n assets: response.assets.map((asset) => this.convertAssetDates(asset)),\n };\n }\n\n /**\n * Move assets to a different folder\n *\n * @example\n * ```typescript\n * await cdn.move({\n * assetIds: ['asset-1', 'asset-2'],\n * folder: '/images/archive',\n * });\n * ```\n */\n async move(request: MoveAssetsRequest): Promise<MoveAssetsResponse> {\n return this.http.post<MoveAssetsResponse>(\"/cdn/assets/move\", request);\n }\n\n /**\n * Get a transformed image URL\n *\n * @example\n * ```typescript\n * const { url } = await cdn.getTransformUrl({\n * assetId: 'asset-id',\n * options: {\n * width: 800,\n * height: 600,\n * fit: 'cover',\n * format: 'webp',\n * quality: 80,\n * },\n * });\n * ```\n */\n async getTransformUrl(request: GetTransformUrlRequest): Promise<GetTransformUrlResponse> {\n return this.http.post<GetTransformUrlResponse>(\"/cdn/transform\", request);\n }\n\n /**\n * Get folder tree for navigation\n *\n * @example\n * ```typescript\n * const tree = await cdn.getFolderTree({\n * projectSlug: 'my-project',\n * maxDepth: 3,\n * });\n * ```\n */\n async getFolderTree(request: GetFolderTreeRequest): Promise<FolderTreeNode[]> {\n const params = new URLSearchParams();\n params.set(\"projectSlug\", request.projectSlug);\n if (request.maxDepth) params.set(\"maxDepth\", request.maxDepth.toString());\n\n const response = await this.http.get<{ tree: FolderTreeNode[] }>(`/cdn/folders/tree?${params.toString()}`);\n return response.tree;\n }\n\n /**\n * Create a new folder\n *\n * @example\n * ```typescript\n * const folder = await cdn.createFolder({\n * projectSlug: 'my-project',\n * name: 'images',\n * });\n * ```\n */\n async createFolder(request: CreateFolderRequest): Promise<Folder> {\n const response = await this.http.post<Folder>(\"/cdn/folders\", request);\n return this.convertFolderDates(response);\n }\n\n /**\n * Delete a folder\n *\n * @example\n * ```typescript\n * await cdn.deleteFolder('folder-id');\n * ```\n */\n async deleteFolder(id: string, deleteContents = false): Promise<{ success: boolean }> {\n const params = new URLSearchParams();\n if (deleteContents) params.set(\"deleteContents\", \"true\");\n\n return this.http.delete<{ success: boolean }>(`/cdn/folders/${id}?${params.toString()}`);\n }\n\n private convertAssetDates(asset: Asset): Asset {\n if (typeof asset.createdAt === \"string\") {\n asset.createdAt = new Date(asset.createdAt);\n }\n if (asset.updatedAt && typeof asset.updatedAt === \"string\") {\n asset.updatedAt = new Date(asset.updatedAt);\n }\n return asset;\n }\n\n private convertFolderDates(folder: Folder): Folder {\n if (typeof folder.createdAt === \"string\") {\n folder.createdAt = new Date(folder.createdAt);\n }\n if (folder.updatedAt && typeof folder.updatedAt === \"string\") {\n folder.updatedAt = new Date(folder.updatedAt);\n }\n return folder;\n }\n\n // ============================================================================\n // Video Transcoding Methods\n // ============================================================================\n\n /**\n * Start a video transcoding job\n *\n * @example\n * ```typescript\n * const job = await cdn.transcode({\n * projectSlug: 'my-project',\n * assetId: 'video-asset-id',\n * outputFormat: 'hls',\n * variants: [\n * { quality: '720p', codec: 'h264' },\n * { quality: '1080p', codec: 'h264' },\n * ],\n * webhookUrl: 'https://your-app.com/webhook',\n * });\n * console.log(`Job started: ${job.id}`);\n * ```\n */\n async transcode(request: TranscodeVideoRequest): Promise<TranscodeJob> {\n const response = await this.http.post<TranscodeJob>(\"/cdn/video/transcode\", request);\n return this.convertJobDates(response);\n }\n\n /**\n * Get a transcoding job by ID\n *\n * @example\n * ```typescript\n * const job = await cdn.getJob('job-id');\n * console.log(`Status: ${job.status}, Progress: ${job.progress}%`);\n * ```\n */\n async getJob(jobId: string): Promise<TranscodeJob> {\n const response = await this.http.get<TranscodeJob>(`/cdn/video/jobs/${jobId}`);\n return this.convertJobDates(response);\n }\n\n /**\n * List transcoding jobs with filters\n *\n * @example\n * ```typescript\n * const { jobs, total } = await cdn.listJobs({\n * projectSlug: 'my-project',\n * status: 'processing',\n * limit: 20,\n * });\n * ```\n */\n async listJobs(request: ListJobsRequest): Promise<ListJobsResponse> {\n const params = new URLSearchParams();\n params.set(\"projectSlug\", request.projectSlug);\n if (request.assetId) params.set(\"assetId\", request.assetId);\n if (request.status) params.set(\"status\", request.status);\n if (request.limit) params.set(\"limit\", request.limit.toString());\n if (request.offset) params.set(\"offset\", request.offset.toString());\n\n const response = await this.http.get<ListJobsResponse>(`/cdn/video/jobs?${params.toString()}`);\n return {\n ...response,\n jobs: response.jobs.map((job) => this.convertJobDates(job)),\n };\n }\n\n /**\n * Cancel a pending or processing transcoding job\n *\n * @example\n * ```typescript\n * await cdn.cancelJob('job-id');\n * ```\n */\n async cancelJob(jobId: string): Promise<{ success: boolean }> {\n return this.http.post<{ success: boolean }>(`/cdn/video/jobs/${jobId}/cancel`, {});\n }\n\n /**\n * Get streaming URLs for a transcoded video\n *\n * @example\n * ```typescript\n * const urls = await cdn.getStreamingUrls('asset-id');\n * console.log(`HLS URL: ${urls.hlsUrl}`);\n * console.log(`MP4 720p: ${urls.mp4Urls.find(u => u.quality === '720p')?.url}`);\n * ```\n */\n async getStreamingUrls(assetId: string): Promise<StreamingUrls> {\n return this.http.get<StreamingUrls>(`/cdn/video/stream/${assetId}`);\n }\n\n /**\n * Generate a thumbnail from a video at a specific timestamp\n *\n * @example\n * ```typescript\n * const thumbnail = await cdn.getThumbnail({\n * assetId: 'video-asset-id',\n * timestamp: 10.5, // 10.5 seconds into the video\n * width: 320,\n * format: 'webp',\n * });\n * console.log(`Thumbnail URL: ${thumbnail.url}`);\n * ```\n */\n async getThumbnail(request: ThumbnailRequest): Promise<ThumbnailResponse> {\n const params = new URLSearchParams();\n params.set(\"timestamp\", request.timestamp.toString());\n if (request.width) params.set(\"width\", request.width.toString());\n if (request.format) params.set(\"format\", request.format);\n\n return this.http.get<ThumbnailResponse>(\n `/cdn/video/thumbnail/${request.assetId}?${params.toString()}`\n );\n }\n\n /**\n * Extract audio from a video file\n *\n * @example\n * ```typescript\n * const { jobId } = await cdn.extractAudio({\n * projectSlug: 'my-project',\n * assetId: 'video-asset-id',\n * format: 'mp3',\n * bitrate: 192,\n * });\n * ```\n */\n async extractAudio(request: ExtractAudioRequest): Promise<ExtractAudioResponse> {\n return this.http.post<ExtractAudioResponse>(\"/cdn/video/extract-audio\", request);\n }\n\n private convertJobDates(job: TranscodeJob): TranscodeJob {\n if (typeof job.createdAt === \"string\") {\n job.createdAt = new Date(job.createdAt);\n }\n if (job.startedAt && typeof job.startedAt === \"string\") {\n job.startedAt = new Date(job.startedAt);\n }\n if (job.completedAt && typeof job.completedAt === \"string\") {\n job.completedAt = new Date(job.completedAt);\n }\n return job;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/lib/http-client.ts","../../src/cdn/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * HTTP client for Stack0 API\n * Handles authentication, request/response formatting, and error handling\n */\n\nexport interface HttpClientConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class HttpClient {\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: HttpClientConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || \"https://api.stack0.dev/v1\";\n }\n\n private getHeaders(includeContentType = true): Record<string, string> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n };\n if (includeContentType) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n return headers;\n }\n\n async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const bodyString = body === undefined ? undefined : JSON.stringify(body);\n const hasBody = bodyString !== undefined;\n\n try {\n const response = await fetch(url, {\n method,\n headers: this.getHeaders(hasBody),\n body: hasBody ? bodyString : undefined,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n const data = await response.json();\n return data as T;\n } catch (error) {\n if (error instanceof Error && \"statusCode\" in error) {\n throw error; // Re-throw our custom errors\n }\n throw this.createError(\"Network error\", error);\n }\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let errorBody: { message: string } | undefined;\n try {\n errorBody = (await response.json()) as { message: string };\n } catch {\n errorBody = { message: response.statusText };\n }\n\n const error = new Error(errorBody?.message || `HTTP ${response.status}`) as Error & {\n statusCode: number;\n code: string;\n response: unknown;\n };\n error.statusCode = response.status;\n error.code = (errorBody as unknown as { code: string } | undefined)?.code ?? \"\";\n error.response = errorBody;\n throw error;\n }\n\n private createError(message: string, cause?: unknown): Error {\n const error = new Error(message) as Error & { cause: unknown };\n error.cause = cause;\n return error;\n }\n\n async get<T>(path: string): Promise<T> {\n return this.request<T>(\"GET\", path);\n }\n\n async post<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"POST\", path, body);\n }\n\n async put<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PUT\", path, body);\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>(\"DELETE\", path);\n }\n\n async deleteWithBody<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"DELETE\", path, body);\n }\n\n async patch<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PATCH\", path, body);\n }\n}\n","/**\n * Stack0 CDN Client\n * Upload, manage, and transform assets\n */\n\nimport { HttpClient, type HttpClientConfig } from \"../lib/http-client\";\nimport type {\n Asset,\n UploadUrlRequest,\n UploadUrlResponse,\n UpdateAssetRequest,\n DeleteAssetsResponse,\n ListAssetsRequest,\n ListAssetsResponse,\n MoveAssetsRequest,\n MoveAssetsResponse,\n TransformOptions,\n GetFolderTreeRequest,\n FolderTreeNode,\n CreateFolderRequest,\n Folder,\n TranscodeVideoRequest,\n TranscodeJob,\n ListJobsRequest,\n ListJobsResponse,\n StreamingUrls,\n ThumbnailRequest,\n ThumbnailResponse,\n ExtractAudioRequest,\n ExtractAudioResponse,\n} from \"./types\";\n\n// Allowed widths that match the CloudFront url-rewriter configuration\nconst ALLOWED_WIDTHS = [256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840];\n\nexport class CDN {\n private http: HttpClient;\n private cdnUrl?: string;\n\n constructor(config: HttpClientConfig, cdnUrl?: string) {\n this.http = new HttpClient(config);\n this.cdnUrl = cdnUrl;\n }\n\n /**\n * Generate a presigned URL for uploading a file\n *\n * @example\n * ```typescript\n * const { uploadUrl, assetId } = await cdn.getUploadUrl({\n * projectSlug: 'my-project',\n * filename: 'image.jpg',\n * mimeType: 'image/jpeg',\n * size: 1024 * 1024,\n * });\n *\n * // Upload file to the presigned URL\n * await fetch(uploadUrl, {\n * method: 'PUT',\n * body: file,\n * headers: { 'Content-Type': 'image/jpeg' },\n * });\n *\n * // Confirm the upload\n * const asset = await cdn.confirmUpload(assetId);\n * ```\n */\n async getUploadUrl(request: UploadUrlRequest): Promise<UploadUrlResponse> {\n const response = await this.http.post<UploadUrlResponse>(\"/cdn/upload\", request);\n\n if (typeof response.expiresAt === \"string\") {\n response.expiresAt = new Date(response.expiresAt);\n }\n\n return response;\n }\n\n /**\n * Confirm that an upload has completed\n */\n async confirmUpload(assetId: string): Promise<Asset> {\n const response = await this.http.post<Asset>(`/cdn/upload/${assetId}/confirm`, {});\n return this.convertAssetDates(response);\n }\n\n /**\n * Upload a file directly (handles presigned URL flow automatically)\n *\n * @example\n * ```typescript\n * const asset = await cdn.upload({\n * projectSlug: 'my-project',\n * file: fileBuffer,\n * filename: 'image.jpg',\n * mimeType: 'image/jpeg',\n * });\n * ```\n */\n async upload(options: {\n projectSlug: string;\n file: Blob | Buffer | ArrayBuffer;\n filename: string;\n mimeType: string;\n folder?: string;\n metadata?: Record<string, unknown>;\n }): Promise<Asset> {\n const { projectSlug, file, filename, mimeType, folder, metadata } = options;\n\n // Get file size\n let size: number;\n if (file instanceof Blob) {\n size = file.size;\n } else if (file instanceof ArrayBuffer) {\n size = file.byteLength;\n } else {\n // Buffer\n size = (file as Buffer).length;\n }\n\n // Get presigned URL\n const { uploadUrl, assetId } = await this.getUploadUrl({\n projectSlug,\n filename,\n mimeType,\n size,\n folder,\n metadata,\n });\n\n // Upload file\n const uploadResponse = await fetch(uploadUrl, {\n method: \"PUT\",\n body: file,\n headers: {\n \"Content-Type\": mimeType,\n },\n });\n\n if (!uploadResponse.ok) {\n throw new Error(`Upload failed: ${uploadResponse.statusText}`);\n }\n\n // Confirm upload\n return this.confirmUpload(assetId);\n }\n\n /**\n * Get an asset by ID\n *\n * @example\n * ```typescript\n * const asset = await cdn.get('asset-id');\n * console.log(asset.cdnUrl);\n * ```\n */\n async get(id: string): Promise<Asset> {\n const response = await this.http.get<Asset>(`/cdn/assets/${id}`);\n return this.convertAssetDates(response);\n }\n\n /**\n * Update asset metadata\n *\n * @example\n * ```typescript\n * const asset = await cdn.update({\n * id: 'asset-id',\n * alt: 'A beautiful sunset',\n * tags: ['nature', 'sunset'],\n * });\n * ```\n */\n async update(request: UpdateAssetRequest): Promise<Asset> {\n const { id, ...data } = request;\n const response = await this.http.patch<Asset>(`/cdn/assets/${id}`, data);\n return this.convertAssetDates(response);\n }\n\n /**\n * Delete an asset\n *\n * @example\n * ```typescript\n * await cdn.delete('asset-id');\n * ```\n */\n async delete(id: string): Promise<{ success: boolean }> {\n // NOTE: Our OpenAPI adapter parses JSON bodies for non-GET methods.\n // Some Fastify setups will throw if Content-Type is JSON but the body is empty.\n // Sending the id in the body keeps this endpoint compatible across adapters.\n return this.http.deleteWithBody<{ success: boolean }>(`/cdn/assets/${id}`, { id });\n }\n\n /**\n * Delete multiple assets\n *\n * @example\n * ```typescript\n * const result = await cdn.deleteMany(['asset-1', 'asset-2']);\n * console.log(`Deleted ${result.deletedCount} assets`);\n * ```\n */\n async deleteMany(ids: string[]): Promise<DeleteAssetsResponse> {\n return this.http.post<DeleteAssetsResponse>(\"/cdn/assets/delete\", { ids });\n }\n\n /**\n * List assets with filters and pagination\n *\n * @example\n * ```typescript\n * const { assets, total, hasMore } = await cdn.list({\n * projectSlug: 'my-project',\n * type: 'image',\n * limit: 20,\n * });\n * ```\n */\n async list(request: ListAssetsRequest): Promise<ListAssetsResponse> {\n const params = new URLSearchParams();\n\n params.set(\"projectSlug\", request.projectSlug);\n if (request.folder !== undefined) params.set(\"folder\", request.folder ?? \"\");\n if (request.type) params.set(\"type\", request.type);\n if (request.status) params.set(\"status\", request.status);\n if (request.search) params.set(\"search\", request.search);\n if (request.tags) params.set(\"tags\", request.tags.join(\",\"));\n if (request.sortBy) params.set(\"sortBy\", request.sortBy);\n if (request.sortOrder) params.set(\"sortOrder\", request.sortOrder);\n if (request.limit) params.set(\"limit\", request.limit.toString());\n if (request.offset) params.set(\"offset\", request.offset.toString());\n\n const response = await this.http.get<ListAssetsResponse>(`/cdn/assets?${params.toString()}`);\n\n return {\n ...response,\n assets: response.assets.map((asset) => this.convertAssetDates(asset)),\n };\n }\n\n /**\n * Move assets to a different folder\n *\n * @example\n * ```typescript\n * await cdn.move({\n * assetIds: ['asset-1', 'asset-2'],\n * folder: '/images/archive',\n * });\n * ```\n */\n async move(request: MoveAssetsRequest): Promise<MoveAssetsResponse> {\n return this.http.post<MoveAssetsResponse>(\"/cdn/assets/move\", request);\n }\n\n /**\n * Get a transformed image URL (client-side, no API call)\n *\n * @example\n * ```typescript\n * // Using asset's cdnUrl directly\n * const url = cdn.getTransformUrl(asset.cdnUrl, {\n * width: 800,\n * height: 600,\n * fit: 'cover',\n * format: 'webp',\n * quality: 80,\n * });\n *\n * // Or using cdnUrl from SDK config + s3Key\n * const url = cdn.getTransformUrl(asset.s3Key, { width: 400 });\n * ```\n */\n getTransformUrl(assetUrlOrS3Key: string, options: TransformOptions): string {\n // Determine base URL\n let baseUrl: string;\n if (assetUrlOrS3Key.startsWith(\"http://\") || assetUrlOrS3Key.startsWith(\"https://\")) {\n // It's already a full URL - extract base and path\n const url = new URL(assetUrlOrS3Key);\n baseUrl = `${url.protocol}//${url.host}${url.pathname}`;\n } else if (this.cdnUrl) {\n // It's an s3Key, use configured CDN URL\n const cdnBase = this.cdnUrl.endsWith(\"/\") ? this.cdnUrl.slice(0, -1) : this.cdnUrl;\n baseUrl = `${cdnBase}/${assetUrlOrS3Key}`;\n } else {\n throw new Error(\"getTransformUrl requires either a full URL or cdnUrl to be configured in Stack0 options\");\n }\n\n // Build query string\n const params = this.buildTransformQuery(options);\n if (!params) {\n return baseUrl;\n }\n return `${baseUrl}?${params}`;\n }\n\n /**\n * Build transform query parameters\n */\n private buildTransformQuery(options: TransformOptions): string {\n const params = new URLSearchParams();\n\n if (options.format) params.set(\"f\", options.format);\n if (options.quality !== undefined) params.set(\"q\", options.quality.toString());\n\n if (options.width !== undefined) {\n // Snap to nearest allowed width for better caching\n const width = this.getNearestWidth(options.width);\n params.set(\"w\", width.toString());\n }\n if (options.height !== undefined) params.set(\"h\", options.height.toString());\n if (options.fit) params.set(\"fit\", options.fit);\n if (options.crop) params.set(\"crop\", options.crop);\n if (options.cropX !== undefined) params.set(\"crop-x\", options.cropX.toString());\n if (options.cropY !== undefined) params.set(\"crop-y\", options.cropY.toString());\n if (options.cropWidth !== undefined) params.set(\"crop-w\", options.cropWidth.toString());\n if (options.cropHeight !== undefined) params.set(\"crop-h\", options.cropHeight.toString());\n if (options.blur !== undefined) params.set(\"blur\", options.blur.toString());\n if (options.sharpen !== undefined) params.set(\"sharpen\", options.sharpen.toString());\n if (options.brightness !== undefined) params.set(\"brightness\", options.brightness.toString());\n if (options.saturation !== undefined) params.set(\"saturation\", options.saturation.toString());\n if (options.grayscale) params.set(\"grayscale\", \"true\");\n if (options.rotate !== undefined) params.set(\"rotate\", options.rotate.toString());\n if (options.flip) params.set(\"flip\", \"y\");\n if (options.flop) params.set(\"flop\", \"x\");\n\n return params.toString();\n }\n\n /**\n * Find the nearest allowed width for optimal caching\n */\n private getNearestWidth(width: number): number {\n return ALLOWED_WIDTHS.reduce((prev, curr) => (Math.abs(curr - width) < Math.abs(prev - width) ? curr : prev));\n }\n\n /**\n * Get folder tree for navigation\n *\n * @example\n * ```typescript\n * const tree = await cdn.getFolderTree({\n * projectSlug: 'my-project',\n * maxDepth: 3,\n * });\n * ```\n */\n async getFolderTree(request: GetFolderTreeRequest): Promise<FolderTreeNode[]> {\n const params = new URLSearchParams();\n params.set(\"projectSlug\", request.projectSlug);\n if (request.maxDepth) params.set(\"maxDepth\", request.maxDepth.toString());\n\n const response = await this.http.get<{ tree: FolderTreeNode[] }>(`/cdn/folders/tree?${params.toString()}`);\n return response.tree;\n }\n\n /**\n * Create a new folder\n *\n * @example\n * ```typescript\n * const folder = await cdn.createFolder({\n * projectSlug: 'my-project',\n * name: 'images',\n * });\n * ```\n */\n async createFolder(request: CreateFolderRequest): Promise<Folder> {\n const response = await this.http.post<Folder>(\"/cdn/folders\", request);\n return this.convertFolderDates(response);\n }\n\n /**\n * Delete a folder\n *\n * @example\n * ```typescript\n * await cdn.deleteFolder('folder-id');\n * ```\n */\n async deleteFolder(id: string, deleteContents = false): Promise<{ success: boolean }> {\n const params = new URLSearchParams();\n if (deleteContents) params.set(\"deleteContents\", \"true\");\n\n return this.http.deleteWithBody<{ success: boolean }>(`/cdn/folders/${id}?${params.toString()}`, {\n id,\n deleteContents,\n });\n }\n\n private convertAssetDates(asset: Asset): Asset {\n if (typeof asset.createdAt === \"string\") {\n asset.createdAt = new Date(asset.createdAt);\n }\n if (asset.updatedAt && typeof asset.updatedAt === \"string\") {\n asset.updatedAt = new Date(asset.updatedAt);\n }\n return asset;\n }\n\n private convertFolderDates(folder: Folder): Folder {\n if (typeof folder.createdAt === \"string\") {\n folder.createdAt = new Date(folder.createdAt);\n }\n if (folder.updatedAt && typeof folder.updatedAt === \"string\") {\n folder.updatedAt = new Date(folder.updatedAt);\n }\n return folder;\n }\n\n // ============================================================================\n // Video Transcoding Methods\n // ============================================================================\n\n /**\n * Start a video transcoding job\n *\n * @example\n * ```typescript\n * const job = await cdn.transcode({\n * projectSlug: 'my-project',\n * assetId: 'video-asset-id',\n * outputFormat: 'hls',\n * variants: [\n * { quality: '720p', codec: 'h264' },\n * { quality: '1080p', codec: 'h264' },\n * ],\n * webhookUrl: 'https://your-app.com/webhook',\n * });\n * console.log(`Job started: ${job.id}`);\n * ```\n */\n async transcode(request: TranscodeVideoRequest): Promise<TranscodeJob> {\n const response = await this.http.post<TranscodeJob>(\"/cdn/video/transcode\", request);\n return this.convertJobDates(response);\n }\n\n /**\n * Get a transcoding job by ID\n *\n * @example\n * ```typescript\n * const job = await cdn.getJob('job-id');\n * console.log(`Status: ${job.status}, Progress: ${job.progress}%`);\n * ```\n */\n async getJob(jobId: string): Promise<TranscodeJob> {\n const response = await this.http.get<TranscodeJob>(`/cdn/video/jobs/${jobId}`);\n return this.convertJobDates(response);\n }\n\n /**\n * List transcoding jobs with filters\n *\n * @example\n * ```typescript\n * const { jobs, total } = await cdn.listJobs({\n * projectSlug: 'my-project',\n * status: 'processing',\n * limit: 20,\n * });\n * ```\n */\n async listJobs(request: ListJobsRequest): Promise<ListJobsResponse> {\n const params = new URLSearchParams();\n params.set(\"projectSlug\", request.projectSlug);\n if (request.assetId) params.set(\"assetId\", request.assetId);\n if (request.status) params.set(\"status\", request.status);\n if (request.limit) params.set(\"limit\", request.limit.toString());\n if (request.offset) params.set(\"offset\", request.offset.toString());\n\n const response = await this.http.get<ListJobsResponse>(`/cdn/video/jobs?${params.toString()}`);\n return {\n ...response,\n jobs: response.jobs.map((job) => this.convertJobDates(job)),\n };\n }\n\n /**\n * Cancel a pending or processing transcoding job\n *\n * @example\n * ```typescript\n * await cdn.cancelJob('job-id');\n * ```\n */\n async cancelJob(jobId: string): Promise<{ success: boolean }> {\n return this.http.post<{ success: boolean }>(`/cdn/video/jobs/${jobId}/cancel`, {});\n }\n\n /**\n * Get streaming URLs for a transcoded video\n *\n * @example\n * ```typescript\n * const urls = await cdn.getStreamingUrls('asset-id');\n * console.log(`HLS URL: ${urls.hlsUrl}`);\n * console.log(`MP4 720p: ${urls.mp4Urls.find(u => u.quality === '720p')?.url}`);\n * ```\n */\n async getStreamingUrls(assetId: string): Promise<StreamingUrls> {\n return this.http.get<StreamingUrls>(`/cdn/video/stream/${assetId}`);\n }\n\n /**\n * Generate a thumbnail from a video at a specific timestamp\n *\n * @example\n * ```typescript\n * const thumbnail = await cdn.getThumbnail({\n * assetId: 'video-asset-id',\n * timestamp: 10.5, // 10.5 seconds into the video\n * width: 320,\n * format: 'webp',\n * });\n * console.log(`Thumbnail URL: ${thumbnail.url}`);\n * ```\n */\n async getThumbnail(request: ThumbnailRequest): Promise<ThumbnailResponse> {\n const params = new URLSearchParams();\n params.set(\"timestamp\", request.timestamp.toString());\n if (request.width) params.set(\"width\", request.width.toString());\n if (request.format) params.set(\"format\", request.format);\n\n return this.http.get<ThumbnailResponse>(`/cdn/video/thumbnail/${request.assetId}?${params.toString()}`);\n }\n\n /**\n * Extract audio from a video file\n *\n * @example\n * ```typescript\n * const { jobId } = await cdn.extractAudio({\n * projectSlug: 'my-project',\n * assetId: 'video-asset-id',\n * format: 'mp3',\n * bitrate: 192,\n * });\n * ```\n */\n async extractAudio(request: ExtractAudioRequest): Promise<ExtractAudioResponse> {\n return this.http.post<ExtractAudioResponse>(\"/cdn/video/extract-audio\", request);\n }\n\n private convertJobDates(job: TranscodeJob): TranscodeJob {\n if (typeof job.createdAt === \"string\") {\n job.createdAt = new Date(job.createdAt);\n }\n if (job.startedAt && typeof job.startedAt === \"string\") {\n job.startedAt = new Date(job.startedAt);\n }\n if (job.completedAt && typeof job.completedAt === \"string\") {\n job.completedAt = new Date(job.completedAt);\n }\n return job;\n }\n}\n"]}