@stack0/sdk 0.5.7 → 0.5.9
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/README.md +1026 -369
- package/dist/cdn/index.d.mts +416 -1
- package/dist/cdn/index.d.ts +416 -1
- package/dist/cdn/index.js +293 -0
- package/dist/cdn/index.js.map +1 -1
- package/dist/cdn/index.mjs +293 -0
- package/dist/cdn/index.mjs.map +1 -1
- package/dist/index.d.mts +760 -3
- package/dist/index.d.ts +760 -3
- package/dist/index.js +837 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +833 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -6
package/dist/cdn/index.mjs
CHANGED
|
@@ -180,6 +180,27 @@ var CDN = class {
|
|
|
180
180
|
}
|
|
181
181
|
return this.confirmUpload(assetId);
|
|
182
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Upload a file from a remote URL (server-side fetch).
|
|
185
|
+
* The server streams the file directly from the source URL into storage,
|
|
186
|
+
* so the client never touches the bytes. Ideal for serverless environments
|
|
187
|
+
* with tight memory limits.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* const asset = await cdn.uploadFromUrl({
|
|
192
|
+
* projectSlug: 'my-project',
|
|
193
|
+
* sourceUrl: 'https://replicate.delivery/output/video.mp4',
|
|
194
|
+
* filename: 'video.mp4',
|
|
195
|
+
* mimeType: 'video/mp4',
|
|
196
|
+
* });
|
|
197
|
+
* console.log(asset.cdnUrl);
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
async uploadFromUrl(request) {
|
|
201
|
+
const response = await this.http.post("/cdn/upload-from-url", request);
|
|
202
|
+
return this.convertAssetDates(response);
|
|
203
|
+
}
|
|
183
204
|
/**
|
|
184
205
|
* Get an asset by ID
|
|
185
206
|
*
|
|
@@ -556,6 +577,80 @@ var CDN = class {
|
|
|
556
577
|
async extractAudio(request) {
|
|
557
578
|
return this.http.post("/cdn/video/extract-audio", request);
|
|
558
579
|
}
|
|
580
|
+
// ============================================================================
|
|
581
|
+
// GIF Generation Methods
|
|
582
|
+
// ============================================================================
|
|
583
|
+
/**
|
|
584
|
+
* Generate an animated GIF from a video segment
|
|
585
|
+
*
|
|
586
|
+
* Creates an optimized GIF from a portion of the video. Uses two-pass
|
|
587
|
+
* palette generation by default for smaller file sizes with better quality.
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* ```typescript
|
|
591
|
+
* const gif = await cdn.generateGif({
|
|
592
|
+
* projectSlug: 'my-project',
|
|
593
|
+
* assetId: 'video-asset-id',
|
|
594
|
+
* startTime: 5, // Start at 5 seconds
|
|
595
|
+
* duration: 3, // 3 second GIF
|
|
596
|
+
* width: 480, // 480px wide
|
|
597
|
+
* fps: 10, // 10 frames per second
|
|
598
|
+
* });
|
|
599
|
+
*
|
|
600
|
+
* // Poll for completion
|
|
601
|
+
* let result = await cdn.getGif(gif.id);
|
|
602
|
+
* while (result?.status === 'pending' || result?.status === 'processing') {
|
|
603
|
+
* await new Promise(r => setTimeout(r, 1000));
|
|
604
|
+
* result = await cdn.getGif(gif.id);
|
|
605
|
+
* }
|
|
606
|
+
*
|
|
607
|
+
* console.log(`GIF URL: ${result?.url}`);
|
|
608
|
+
* ```
|
|
609
|
+
*/
|
|
610
|
+
async generateGif(request) {
|
|
611
|
+
const response = await this.http.post("/cdn/video/gif", request);
|
|
612
|
+
return this.convertGifDates(response);
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Get a specific GIF by ID
|
|
616
|
+
*
|
|
617
|
+
* @example
|
|
618
|
+
* ```typescript
|
|
619
|
+
* const gif = await cdn.getGif('gif-id');
|
|
620
|
+
* if (gif?.status === 'completed') {
|
|
621
|
+
* console.log(`GIF URL: ${gif.url}`);
|
|
622
|
+
* console.log(`Size: ${gif.sizeBytes} bytes`);
|
|
623
|
+
* }
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
async getGif(gifId) {
|
|
627
|
+
const response = await this.http.get(`/cdn/video/gif/${gifId}`);
|
|
628
|
+
return response ? this.convertGifDates(response) : null;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* List all GIFs generated for a video asset
|
|
632
|
+
*
|
|
633
|
+
* @example
|
|
634
|
+
* ```typescript
|
|
635
|
+
* const gifs = await cdn.listGifs({ assetId: 'video-asset-id' });
|
|
636
|
+
* for (const gif of gifs) {
|
|
637
|
+
* console.log(`GIF at ${gif.startTime}s: ${gif.url}`);
|
|
638
|
+
* }
|
|
639
|
+
* ```
|
|
640
|
+
*/
|
|
641
|
+
async listGifs(request) {
|
|
642
|
+
const response = await this.http.get(`/cdn/video/${request.assetId}/gifs`);
|
|
643
|
+
return response.map((gif) => this.convertGifDates(gif));
|
|
644
|
+
}
|
|
645
|
+
convertGifDates(gif) {
|
|
646
|
+
if (typeof gif.createdAt === "string") {
|
|
647
|
+
gif.createdAt = new Date(gif.createdAt);
|
|
648
|
+
}
|
|
649
|
+
if (gif.completedAt && typeof gif.completedAt === "string") {
|
|
650
|
+
gif.completedAt = new Date(gif.completedAt);
|
|
651
|
+
}
|
|
652
|
+
return gif;
|
|
653
|
+
}
|
|
559
654
|
convertJobDates(job) {
|
|
560
655
|
if (typeof job.createdAt === "string") {
|
|
561
656
|
job.createdAt = new Date(job.createdAt);
|
|
@@ -1158,6 +1253,204 @@ var CDN = class {
|
|
|
1158
1253
|
convertMergeJobWithOutputDates(job) {
|
|
1159
1254
|
return this.convertMergeJobDates(job);
|
|
1160
1255
|
}
|
|
1256
|
+
// ============================================================================
|
|
1257
|
+
// S3 Import Methods
|
|
1258
|
+
// ============================================================================
|
|
1259
|
+
/**
|
|
1260
|
+
* Create an S3 import job to bulk import files from an external S3 bucket.
|
|
1261
|
+
* Requires Pro plan or higher.
|
|
1262
|
+
*
|
|
1263
|
+
* @example
|
|
1264
|
+
* ```typescript
|
|
1265
|
+
* // Using IAM credentials
|
|
1266
|
+
* const job = await cdn.createImport({
|
|
1267
|
+
* projectSlug: 'my-project',
|
|
1268
|
+
* sourceBucket: 'my-external-bucket',
|
|
1269
|
+
* sourceRegion: 'us-east-1',
|
|
1270
|
+
* sourcePrefix: 'images/',
|
|
1271
|
+
* authType: 'iam_credentials',
|
|
1272
|
+
* accessKeyId: 'AKIA...',
|
|
1273
|
+
* secretAccessKey: 'secret...',
|
|
1274
|
+
* pathMode: 'flatten',
|
|
1275
|
+
* notifyEmail: 'admin@example.com',
|
|
1276
|
+
* });
|
|
1277
|
+
*
|
|
1278
|
+
* // Using role assumption
|
|
1279
|
+
* const job = await cdn.createImport({
|
|
1280
|
+
* projectSlug: 'my-project',
|
|
1281
|
+
* sourceBucket: 'partner-bucket',
|
|
1282
|
+
* sourceRegion: 'eu-west-1',
|
|
1283
|
+
* authType: 'role_assumption',
|
|
1284
|
+
* roleArn: 'arn:aws:iam::123456789012:role/Stack0ImportRole',
|
|
1285
|
+
* externalId: 'optional-external-id',
|
|
1286
|
+
* pathMode: 'preserve',
|
|
1287
|
+
* targetFolder: '/imported',
|
|
1288
|
+
* });
|
|
1289
|
+
*
|
|
1290
|
+
* console.log(`Import job started: ${job.importId}`);
|
|
1291
|
+
* ```
|
|
1292
|
+
*/
|
|
1293
|
+
async createImport(request) {
|
|
1294
|
+
const response = await this.http.post("/cdn/imports", request);
|
|
1295
|
+
return this.convertCreateImportDates(response);
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Get an import job by ID
|
|
1299
|
+
*
|
|
1300
|
+
* @example
|
|
1301
|
+
* ```typescript
|
|
1302
|
+
* const job = await cdn.getImport('import-id');
|
|
1303
|
+
* console.log(`Status: ${job.status}`);
|
|
1304
|
+
* console.log(`Progress: ${job.processedFiles}/${job.totalFiles} files`);
|
|
1305
|
+
* console.log(`Bytes: ${job.processedBytes}/${job.totalBytes}`);
|
|
1306
|
+
* ```
|
|
1307
|
+
*/
|
|
1308
|
+
async getImport(importId) {
|
|
1309
|
+
const response = await this.http.get(`/cdn/imports/${importId}`);
|
|
1310
|
+
return response ? this.convertImportJobDates(response) : null;
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* List import jobs with pagination and filters
|
|
1314
|
+
*
|
|
1315
|
+
* @example
|
|
1316
|
+
* ```typescript
|
|
1317
|
+
* const { imports, total, hasMore } = await cdn.listImports({
|
|
1318
|
+
* projectSlug: 'my-project',
|
|
1319
|
+
* status: 'importing',
|
|
1320
|
+
* limit: 20,
|
|
1321
|
+
* });
|
|
1322
|
+
*
|
|
1323
|
+
* for (const job of imports) {
|
|
1324
|
+
* console.log(`${job.sourceBucket}: ${job.processedFiles}/${job.totalFiles}`);
|
|
1325
|
+
* }
|
|
1326
|
+
* ```
|
|
1327
|
+
*/
|
|
1328
|
+
async listImports(request) {
|
|
1329
|
+
const params = new URLSearchParams();
|
|
1330
|
+
params.set("projectSlug", request.projectSlug);
|
|
1331
|
+
if (request.environment) params.set("environment", request.environment);
|
|
1332
|
+
if (request.status) params.set("status", request.status);
|
|
1333
|
+
if (request.sortBy) params.set("sortBy", request.sortBy);
|
|
1334
|
+
if (request.sortOrder) params.set("sortOrder", request.sortOrder);
|
|
1335
|
+
if (request.limit) params.set("limit", request.limit.toString());
|
|
1336
|
+
if (request.offset) params.set("offset", request.offset.toString());
|
|
1337
|
+
const response = await this.http.get(`/cdn/imports?${params.toString()}`);
|
|
1338
|
+
return {
|
|
1339
|
+
...response,
|
|
1340
|
+
imports: response.imports.map((job) => this.convertImportJobSummaryDates(job))
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1344
|
+
* Cancel a running import job
|
|
1345
|
+
*
|
|
1346
|
+
* Files already imported will remain. Only pending/validating/importing jobs can be cancelled.
|
|
1347
|
+
*
|
|
1348
|
+
* @example
|
|
1349
|
+
* ```typescript
|
|
1350
|
+
* const result = await cdn.cancelImport('import-id');
|
|
1351
|
+
* console.log(`Cancelled: ${result.success}`);
|
|
1352
|
+
* ```
|
|
1353
|
+
*/
|
|
1354
|
+
async cancelImport(importId) {
|
|
1355
|
+
return this.http.post(`/cdn/imports/${importId}/cancel`, {});
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Retry failed files in a completed or failed import job
|
|
1359
|
+
*
|
|
1360
|
+
* This resets failed files to pending and re-queues the import for processing.
|
|
1361
|
+
*
|
|
1362
|
+
* @example
|
|
1363
|
+
* ```typescript
|
|
1364
|
+
* const result = await cdn.retryImport('import-id');
|
|
1365
|
+
* console.log(`Retrying ${result.retriedCount} files`);
|
|
1366
|
+
* ```
|
|
1367
|
+
*/
|
|
1368
|
+
async retryImport(importId) {
|
|
1369
|
+
return this.http.post(`/cdn/imports/${importId}/retry`, {});
|
|
1370
|
+
}
|
|
1371
|
+
/**
|
|
1372
|
+
* List files in an import job with optional status filter
|
|
1373
|
+
*
|
|
1374
|
+
* @example
|
|
1375
|
+
* ```typescript
|
|
1376
|
+
* // List all files
|
|
1377
|
+
* const { files, total } = await cdn.listImportFiles({
|
|
1378
|
+
* importId: 'import-id',
|
|
1379
|
+
* limit: 100,
|
|
1380
|
+
* });
|
|
1381
|
+
*
|
|
1382
|
+
* // List only failed files
|
|
1383
|
+
* const { files: failedFiles } = await cdn.listImportFiles({
|
|
1384
|
+
* importId: 'import-id',
|
|
1385
|
+
* status: 'failed',
|
|
1386
|
+
* });
|
|
1387
|
+
*
|
|
1388
|
+
* for (const file of failedFiles) {
|
|
1389
|
+
* console.log(`${file.sourceKey}: ${file.errorMessage}`);
|
|
1390
|
+
* }
|
|
1391
|
+
* ```
|
|
1392
|
+
*/
|
|
1393
|
+
async listImportFiles(request) {
|
|
1394
|
+
const params = new URLSearchParams();
|
|
1395
|
+
if (request.status) params.set("status", request.status);
|
|
1396
|
+
if (request.sortBy) params.set("sortBy", request.sortBy);
|
|
1397
|
+
if (request.sortOrder) params.set("sortOrder", request.sortOrder);
|
|
1398
|
+
if (request.limit) params.set("limit", request.limit.toString());
|
|
1399
|
+
if (request.offset) params.set("offset", request.offset.toString());
|
|
1400
|
+
const query = params.toString();
|
|
1401
|
+
const response = await this.http.get(
|
|
1402
|
+
`/cdn/imports/${request.importId}/files${query ? `?${query}` : ""}`
|
|
1403
|
+
);
|
|
1404
|
+
return {
|
|
1405
|
+
...response,
|
|
1406
|
+
files: response.files.map((file) => this.convertImportFileDates(file))
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
convertCreateImportDates(response) {
|
|
1410
|
+
if (typeof response.createdAt === "string") {
|
|
1411
|
+
response.createdAt = new Date(response.createdAt);
|
|
1412
|
+
}
|
|
1413
|
+
return response;
|
|
1414
|
+
}
|
|
1415
|
+
convertImportJobDates(job) {
|
|
1416
|
+
if (typeof job.createdAt === "string") {
|
|
1417
|
+
job.createdAt = new Date(job.createdAt);
|
|
1418
|
+
}
|
|
1419
|
+
if (job.updatedAt && typeof job.updatedAt === "string") {
|
|
1420
|
+
job.updatedAt = new Date(job.updatedAt);
|
|
1421
|
+
}
|
|
1422
|
+
if (job.startedAt && typeof job.startedAt === "string") {
|
|
1423
|
+
job.startedAt = new Date(job.startedAt);
|
|
1424
|
+
}
|
|
1425
|
+
if (job.completedAt && typeof job.completedAt === "string") {
|
|
1426
|
+
job.completedAt = new Date(job.completedAt);
|
|
1427
|
+
}
|
|
1428
|
+
return job;
|
|
1429
|
+
}
|
|
1430
|
+
convertImportJobSummaryDates(job) {
|
|
1431
|
+
if (typeof job.createdAt === "string") {
|
|
1432
|
+
job.createdAt = new Date(job.createdAt);
|
|
1433
|
+
}
|
|
1434
|
+
if (job.startedAt && typeof job.startedAt === "string") {
|
|
1435
|
+
job.startedAt = new Date(job.startedAt);
|
|
1436
|
+
}
|
|
1437
|
+
if (job.completedAt && typeof job.completedAt === "string") {
|
|
1438
|
+
job.completedAt = new Date(job.completedAt);
|
|
1439
|
+
}
|
|
1440
|
+
return job;
|
|
1441
|
+
}
|
|
1442
|
+
convertImportFileDates(file) {
|
|
1443
|
+
if (typeof file.createdAt === "string") {
|
|
1444
|
+
file.createdAt = new Date(file.createdAt);
|
|
1445
|
+
}
|
|
1446
|
+
if (file.completedAt && typeof file.completedAt === "string") {
|
|
1447
|
+
file.completedAt = new Date(file.completedAt);
|
|
1448
|
+
}
|
|
1449
|
+
if (file.lastAttemptAt && typeof file.lastAttemptAt === "string") {
|
|
1450
|
+
file.lastAttemptAt = new Date(file.lastAttemptAt);
|
|
1451
|
+
}
|
|
1452
|
+
return file;
|
|
1453
|
+
}
|
|
1161
1454
|
};
|
|
1162
1455
|
|
|
1163
1456
|
export { CDN };
|