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