| 307 | }; |
| 308 | |
| 309 | export const uploadFiles = async ( |
| 310 | files: string[], |
| 311 | { dryRun, concurrency, progress }: UploadOptionsDto, |
| 312 | ): Promise<Asset[]> => { |
| 313 | if (files.length === 0) { |
| 314 | console.log('All assets were already uploaded, nothing to do.'); |
| 315 | return []; |
| 316 | } |
| 317 | |
| 318 | // Compute total size first |
| 319 | let totalSize = 0; |
| 320 | const statsMap = new Map<string, Stats>(); |
| 321 | for (const filepath of files) { |
| 322 | const stats = await stat(filepath); |
| 323 | statsMap.set(filepath, stats); |
| 324 | totalSize += stats.size; |
| 325 | } |
| 326 | |
| 327 | if (dryRun) { |
| 328 | console.log(`Would have uploaded ${files.length} asset${s(files.length)} (${byteSize(totalSize)})`); |
| 329 | return files.map((filepath) => ({ id: '', filepath })); |
| 330 | } |
| 331 | |
| 332 | let uploadProgress: SingleBar | undefined; |
| 333 | |
| 334 | if (progress) { |
| 335 | uploadProgress = new SingleBar( |
| 336 | { |
| 337 | format: 'Uploading assets | {bar} | {percentage}% | ETA: {eta_formatted} | {value_formatted}/{total_formatted}', |
| 338 | }, |
| 339 | Presets.shades_classic, |
| 340 | ); |
| 341 | } else { |
| 342 | console.log(`Uploading ${files.length} asset${s(files.length)} (${byteSize(totalSize)})`); |
| 343 | } |
| 344 | uploadProgress?.start(totalSize, 0); |
| 345 | uploadProgress?.update({ value_formatted: 0, total_formatted: byteSize(totalSize) }); |
| 346 | |
| 347 | let duplicateCount = 0; |
| 348 | let duplicateSize = 0; |
| 349 | let successCount = 0; |
| 350 | let successSize = 0; |
| 351 | |
| 352 | const newAssets: Asset[] = []; |
| 353 | |
| 354 | const queue = new Queue<string, AssetMediaResponseDto>( |
| 355 | async (filepath: string) => { |
| 356 | const stats = statsMap.get(filepath); |
| 357 | if (!stats) { |
| 358 | throw new Error(`Stats not found for ${filepath}`); |
| 359 | } |
| 360 | |
| 361 | const response = await uploadFile(filepath, stats); |
| 362 | newAssets.push({ id: response.id, filepath }); |
| 363 | if (response.status === AssetMediaStatus.Duplicate) { |
| 364 | duplicateCount++; |
| 365 | duplicateSize += stats.size ?? 0; |
| 366 | } else { |