@stack0/sdk 0.5.8 → 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.
@@ -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
  *
@@ -1232,6 +1253,204 @@ var CDN = class {
1232
1253
  convertMergeJobWithOutputDates(job) {
1233
1254
  return this.convertMergeJobDates(job);
1234
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
+ }
1235
1454
  };
1236
1455
 
1237
1456
  export { CDN };