@stack0/sdk 0.5.17 → 0.6.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.
package/dist/cdn/index.js CHANGED
@@ -1005,6 +1005,7 @@ var CDN = class {
1005
1005
  const params = new URLSearchParams();
1006
1006
  if (request.projectSlug) params.set("projectSlug", request.projectSlug);
1007
1007
  if (request.environment) params.set("environment", request.environment);
1008
+ if (request.folder) params.set("folder", request.folder);
1008
1009
  if (request.periodStart) {
1009
1010
  const date = request.periodStart instanceof Date ? request.periodStart.toISOString() : request.periodStart;
1010
1011
  params.set("periodStart", date);
@@ -1064,6 +1065,36 @@ var CDN = class {
1064
1065
  const query = params.toString();
1065
1066
  return this.http.get(`/cdn/usage/storage-breakdown${query ? `?${query}` : ""}`);
1066
1067
  }
1068
+ /**
1069
+ * Get total stored bytes for a project or folder, derived assets included.
1070
+ *
1071
+ * Totals uploads plus everything the pipelines derived from them — video renditions, HLS
1072
+ * segments and manifests, thumbnails, GIFs — in one call. Use this to meter a plan limit:
1073
+ * paging `list()` and summing `size` counts uploads only, and an HLS ladder typically runs
1074
+ * well past the size of the source it came from.
1075
+ *
1076
+ * Check `unmeasuredAssets`. A nonzero value means some assets have derivatives whose bytes
1077
+ * have not been measured, so `totalBytes` is a floor rather than the full number.
1078
+ *
1079
+ * @example
1080
+ * ```typescript
1081
+ * const usage = await cdn.getStorageUsage({
1082
+ * projectSlug: 'my-project',
1083
+ * folder: '/customers/acme',
1084
+ * });
1085
+ * console.log(`${usage.totalFormatted} across ${usage.objectCount} objects`);
1086
+ * console.log(` uploads: ${usage.breakdown.originals.bytesFormatted}`);
1087
+ * console.log(` derived: ${usage.breakdown.derived.bytesFormatted}`);
1088
+ * ```
1089
+ */
1090
+ async getStorageUsage(request = {}) {
1091
+ const params = new URLSearchParams();
1092
+ if (request.projectSlug) params.set("projectSlug", request.projectSlug);
1093
+ if (request.environment) params.set("environment", request.environment);
1094
+ if (request.folder) params.set("folder", request.folder);
1095
+ const query = params.toString();
1096
+ return this.http.get(`/cdn/usage/storage${query ? `?${query}` : ""}`);
1097
+ }
1067
1098
  convertUsageDates(usage) {
1068
1099
  if (typeof usage.periodStart === "string") {
1069
1100
  usage.periodStart = new Date(usage.periodStart);
@@ -1340,6 +1371,112 @@ var CDN = class {
1340
1371
  return this.convertMergeJobDates(job);
1341
1372
  }
1342
1373
  // ============================================================================
1374
+ // Video Render Methods
1375
+ // ============================================================================
1376
+ /**
1377
+ * Render a declarative video spec into a video asset
1378
+ *
1379
+ * The spec describes scenes, layers, timing and media as data. There are no
1380
+ * compositions to write and no code to upload — Stack0 owns the renderer.
1381
+ *
1382
+ * `@stack0/video-spec` has the full types, validation and worked examples;
1383
+ * validating locally before you POST turns a round trip into a type error.
1384
+ *
1385
+ * @example
1386
+ * ```typescript
1387
+ * const job = await cdn.createRenderJob({
1388
+ * projectSlug: 'my-project',
1389
+ * spec: {
1390
+ * canvas: { width: 1080, height: 1920, fps: 30 },
1391
+ * audio: [{ src: musicAssetId, volume: 0.34 }],
1392
+ * scenes: [
1393
+ * {
1394
+ * id: 'hook',
1395
+ * duration: 2.5,
1396
+ * layers: [
1397
+ * { type: 'image', src: afterImageAssetId, zoom: { from: 1, to: 1.06 } },
1398
+ * { type: 'caption', text: 'i told my mom\nthe kitchen exploded', position: 'upperThird' },
1399
+ * ],
1400
+ * },
1401
+ * {
1402
+ * // No duration: the thread derives its own length from the messages
1403
+ * id: 'payoff',
1404
+ * layers: [
1405
+ * {
1406
+ * type: 'messageThread',
1407
+ * recipient: 'Mom',
1408
+ * imageSrc: afterImageAssetId,
1409
+ * messages: [
1410
+ * { sender: 'recipient', text: 'you home?', history: true },
1411
+ * { sender: 'user', text: '[IMAGE]' },
1412
+ * { sender: 'recipient', text: 'WHAT IS THAT' },
1413
+ * ],
1414
+ * },
1415
+ * ],
1416
+ * },
1417
+ * ],
1418
+ * },
1419
+ * webhookUrl: 'https://your-app.com/webhook',
1420
+ * });
1421
+ * console.log(job.durationInFrames); // known before rendering starts
1422
+ * ```
1423
+ */
1424
+ async createRenderJob(request) {
1425
+ const response = await this.http.post("/cdn/video/render", request);
1426
+ return this.convertRenderJobDates(response);
1427
+ }
1428
+ /**
1429
+ * Get a render job by ID with output asset details
1430
+ *
1431
+ * @example
1432
+ * ```typescript
1433
+ * const job = await cdn.getRenderJob('job-id');
1434
+ * if (job.status === 'completed' && job.outputAsset) {
1435
+ * console.log(`Output video: ${job.outputAsset.cdnUrl}`);
1436
+ * }
1437
+ * ```
1438
+ */
1439
+ async getRenderJob(jobId) {
1440
+ const response = await this.http.get(`/cdn/video/render/${jobId}`);
1441
+ return this.convertRenderJobDates(response);
1442
+ }
1443
+ /**
1444
+ * List render jobs with optional filters
1445
+ */
1446
+ async listRenderJobs(request) {
1447
+ const params = new URLSearchParams();
1448
+ params.set("projectSlug", request.projectSlug);
1449
+ if (request.status) params.set("status", request.status);
1450
+ if (request.limit) params.set("limit", request.limit.toString());
1451
+ if (request.offset) params.set("offset", request.offset.toString());
1452
+ const response = await this.http.get(`/cdn/video/render?${params.toString()}`);
1453
+ return {
1454
+ ...response,
1455
+ jobs: response.jobs.map((job) => this.convertRenderJobDates(job))
1456
+ };
1457
+ }
1458
+ /**
1459
+ * Cancel a pending or processing render job
1460
+ */
1461
+ async cancelRenderJob(jobId) {
1462
+ return this.http.post(`/cdn/video/render/${jobId}/cancel`, {});
1463
+ }
1464
+ convertRenderJobDates(job) {
1465
+ if (typeof job.createdAt === "string") {
1466
+ job.createdAt = new Date(job.createdAt);
1467
+ }
1468
+ if (job.updatedAt && typeof job.updatedAt === "string") {
1469
+ job.updatedAt = new Date(job.updatedAt);
1470
+ }
1471
+ if (job.startedAt && typeof job.startedAt === "string") {
1472
+ job.startedAt = new Date(job.startedAt);
1473
+ }
1474
+ if (job.completedAt && typeof job.completedAt === "string") {
1475
+ job.completedAt = new Date(job.completedAt);
1476
+ }
1477
+ return job;
1478
+ }
1479
+ // ============================================================================
1343
1480
  // S3 Import Methods
1344
1481
  // ============================================================================
1345
1482
  /**