@gallop.software/studio 1.2.1 → 1.2.3

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.
@@ -311,6 +311,22 @@ async function deleteFromCdn(imageKey, hasThumbnails) {
311
311
  }
312
312
 
313
313
  // src/handlers/list.ts
314
+ function getExistingThumbnails(originalPath, entry) {
315
+ const thumbnails = [];
316
+ if (entry.f) {
317
+ thumbnails.push({ path: _chunkWOHZ4LYGjs.getThumbnailPath.call(void 0, originalPath, "full"), size: "f" });
318
+ }
319
+ if (entry.lg) {
320
+ thumbnails.push({ path: _chunkWOHZ4LYGjs.getThumbnailPath.call(void 0, originalPath, "lg"), size: "lg" });
321
+ }
322
+ if (entry.md) {
323
+ thumbnails.push({ path: _chunkWOHZ4LYGjs.getThumbnailPath.call(void 0, originalPath, "md"), size: "md" });
324
+ }
325
+ if (entry.sm) {
326
+ thumbnails.push({ path: _chunkWOHZ4LYGjs.getThumbnailPath.call(void 0, originalPath, "sm"), size: "sm" });
327
+ }
328
+ return thumbnails;
329
+ }
314
330
  async function handleList(request) {
315
331
  const searchParams = request.nextUrl.searchParams;
316
332
  const requestedPath = searchParams.get("path") || "public";
@@ -325,6 +341,84 @@ async function handleList(request) {
325
341
  const seenFolders = /* @__PURE__ */ new Set();
326
342
  const metaKeys = fileEntries.map(([key]) => key);
327
343
  const isInsideImagesFolder = relativePath === "images" || relativePath.startsWith("images/");
344
+ if (isInsideImagesFolder) {
345
+ const imagesSubPath = relativePath.replace(/^images\/?/, "");
346
+ const imagesPrefix = imagesSubPath ? `/${imagesSubPath}/` : "/";
347
+ const allThumbnails = [];
348
+ for (const [key, entry] of fileEntries) {
349
+ if (_chunkWOHZ4LYGjs.isProcessed.call(void 0, entry)) {
350
+ const thumbnails = getExistingThumbnails(key, entry);
351
+ for (const thumb of thumbnails) {
352
+ allThumbnails.push({ ...thumb, originalKey: key });
353
+ }
354
+ }
355
+ }
356
+ for (const thumb of allThumbnails) {
357
+ const thumbRelative = thumb.path.replace(/^\/images\/?/, "");
358
+ if (imagesSubPath === "") {
359
+ const slashIndex = thumbRelative.indexOf("/");
360
+ if (slashIndex === -1) {
361
+ const fileName = thumbRelative;
362
+ items.push({
363
+ name: fileName,
364
+ path: `public/images/${fileName}`,
365
+ type: "file",
366
+ thumbnail: thumb.path,
367
+ hasThumbnail: false,
368
+ isProtected: true
369
+ });
370
+ } else {
371
+ const folderName = thumbRelative.slice(0, slashIndex);
372
+ if (!seenFolders.has(folderName)) {
373
+ seenFolders.add(folderName);
374
+ const folderPrefix = `/${folderName}/`;
375
+ const fileCount = allThumbnails.filter(
376
+ (t) => t.path.replace(/^\/images/, "").startsWith(folderPrefix)
377
+ ).length;
378
+ items.push({
379
+ name: folderName,
380
+ path: `public/images/${folderName}`,
381
+ type: "folder",
382
+ fileCount,
383
+ isProtected: true
384
+ });
385
+ }
386
+ }
387
+ } else {
388
+ if (!thumbRelative.startsWith(imagesSubPath + "/") && thumbRelative !== imagesSubPath) continue;
389
+ const remaining = thumbRelative.slice(imagesSubPath.length + 1);
390
+ if (!remaining) continue;
391
+ const slashIndex = remaining.indexOf("/");
392
+ if (slashIndex === -1) {
393
+ items.push({
394
+ name: remaining,
395
+ path: `public/images/${imagesSubPath}/${remaining}`,
396
+ type: "file",
397
+ thumbnail: thumb.path,
398
+ hasThumbnail: false,
399
+ isProtected: true
400
+ });
401
+ } else {
402
+ const folderName = remaining.slice(0, slashIndex);
403
+ if (!seenFolders.has(folderName)) {
404
+ seenFolders.add(folderName);
405
+ const folderPrefix = `${imagesSubPath}/${folderName}/`;
406
+ const fileCount = allThumbnails.filter(
407
+ (t) => t.path.replace(/^\/images\//, "").startsWith(folderPrefix)
408
+ ).length;
409
+ items.push({
410
+ name: folderName,
411
+ path: `public/images/${imagesSubPath}/${folderName}`,
412
+ type: "folder",
413
+ fileCount,
414
+ isProtected: true
415
+ });
416
+ }
417
+ }
418
+ }
419
+ }
420
+ return _server.NextResponse.json({ items });
421
+ }
328
422
  const absoluteDir = _path2.default.join(process.cwd(), requestedPath);
329
423
  try {
330
424
  const dirEntries = await _fs.promises.readdir(absoluteDir, { withFileTypes: true });
@@ -336,12 +430,11 @@ async function handleList(request) {
336
430
  const isImagesFolder = entry.name === "images" && !relativePath;
337
431
  const folderPath = relativePath ? `public/${relativePath}/${entry.name}` : `public/${entry.name}`;
338
432
  let fileCount = 0;
339
- if (isInsideImagesFolder || isImagesFolder) {
340
- const subDir = _path2.default.join(absoluteDir, entry.name);
341
- try {
342
- const subEntries = await _fs.promises.readdir(subDir);
343
- fileCount = subEntries.filter((f) => !f.startsWith(".")).length;
344
- } catch (e6) {
433
+ if (isImagesFolder) {
434
+ for (const [key, metaEntry] of fileEntries) {
435
+ if (_chunkWOHZ4LYGjs.isProcessed.call(void 0, metaEntry)) {
436
+ fileCount += getExistingThumbnails(key, metaEntry).length;
437
+ }
345
438
  }
346
439
  } else {
347
440
  const folderPrefix = pathPrefix === "/" ? `/${entry.name}/` : `${pathPrefix}${entry.name}/`;
@@ -354,31 +447,29 @@ async function handleList(request) {
354
447
  path: folderPath,
355
448
  type: "folder",
356
449
  fileCount,
357
- isProtected: isImagesFolder || isInsideImagesFolder
450
+ isProtected: isImagesFolder
358
451
  });
359
452
  }
360
- } else if (isInsideImagesFolder) {
361
- const filePath = relativePath ? `public/${relativePath}/${entry.name}` : `public/${entry.name}`;
362
- const fullPath = _path2.default.join(absoluteDir, entry.name);
363
- let fileSize;
364
- try {
365
- const stats = await _fs.promises.stat(fullPath);
366
- fileSize = stats.size;
367
- } catch (e7) {
368
- }
369
- const isImage = isImageFile(entry.name);
370
- items.push({
371
- name: entry.name,
372
- path: filePath,
373
- type: "file",
374
- size: fileSize,
375
- thumbnail: isImage ? `/${relativePath}/${entry.name}` : void 0,
376
- hasThumbnail: false,
377
- isProtected: true
378
- });
379
453
  }
380
454
  }
381
- } catch (e8) {
455
+ } catch (e6) {
456
+ }
457
+ if (!relativePath && !seenFolders.has("images")) {
458
+ let thumbnailCount = 0;
459
+ for (const [key, entry] of fileEntries) {
460
+ if (_chunkWOHZ4LYGjs.isProcessed.call(void 0, entry)) {
461
+ thumbnailCount += getExistingThumbnails(key, entry).length;
462
+ }
463
+ }
464
+ if (thumbnailCount > 0) {
465
+ items.push({
466
+ name: "images",
467
+ path: "public/images",
468
+ type: "folder",
469
+ fileCount: thumbnailCount,
470
+ isProtected: true
471
+ });
472
+ }
382
473
  }
383
474
  if (fileEntries.length === 0 && items.length === 0) {
384
475
  return _server.NextResponse.json({ items: [], isEmpty: true });
@@ -430,7 +521,7 @@ async function handleList(request) {
430
521
  await _fs.promises.access(localThumbPath);
431
522
  thumbnail = thumbPath;
432
523
  hasThumbnail = true;
433
- } catch (e9) {
524
+ } catch (e7) {
434
525
  thumbnail = key;
435
526
  hasThumbnail = false;
436
527
  }
@@ -449,7 +540,7 @@ async function handleList(request) {
449
540
  const filePath = _path2.default.join(process.cwd(), "public", key);
450
541
  const stats = await _fs.promises.stat(filePath);
451
542
  fileSize = stats.size;
452
- } catch (e10) {
543
+ } catch (e8) {
453
544
  }
454
545
  }
455
546
  items.push({
@@ -511,7 +602,7 @@ async function handleSearch(request) {
511
602
  await _fs.promises.access(localThumbPath);
512
603
  thumbnail = thumbPath;
513
604
  hasThumbnail = true;
514
- } catch (e11) {
605
+ } catch (e9) {
515
606
  thumbnail = key;
516
607
  hasThumbnail = false;
517
608
  }
@@ -567,7 +658,7 @@ async function handleListFolders() {
567
658
  await scanDir(_path2.default.join(dir, entry.name), folderRelPath);
568
659
  }
569
660
  }
570
- } catch (e12) {
661
+ } catch (e10) {
571
662
  }
572
663
  }
573
664
  const publicDir = _path2.default.join(process.cwd(), "public");
@@ -707,7 +798,7 @@ async function handleUpload(request) {
707
798
  meta[imageKey] = {
708
799
  o: { w: metadata.width || 0, h: metadata.height || 0 }
709
800
  };
710
- } catch (e13) {
801
+ } catch (e11) {
711
802
  meta[imageKey] = { o: { w: 0, h: 0 } };
712
803
  }
713
804
  } else {
@@ -757,7 +848,7 @@ async function handleDelete(request) {
757
848
  const absoluteThumbPath = _path2.default.join(process.cwd(), "public", thumbPath);
758
849
  try {
759
850
  await _fs.promises.unlink(absoluteThumbPath);
760
- } catch (e14) {
851
+ } catch (e12) {
761
852
  }
762
853
  }
763
854
  }
@@ -773,14 +864,14 @@ async function handleDelete(request) {
773
864
  const absoluteThumbPath = _path2.default.join(process.cwd(), "public", thumbPath);
774
865
  try {
775
866
  await _fs.promises.unlink(absoluteThumbPath);
776
- } catch (e15) {
867
+ } catch (e13) {
777
868
  }
778
869
  }
779
870
  }
780
871
  delete meta[imageKey];
781
872
  }
782
873
  }
783
- } catch (e16) {
874
+ } catch (e14) {
784
875
  if (entry) {
785
876
  delete meta[imageKey];
786
877
  } else {
@@ -833,7 +924,7 @@ async function handleCreateFolder(request) {
833
924
  try {
834
925
  await _fs.promises.access(folderPath);
835
926
  return _server.NextResponse.json({ error: "A folder with this name already exists" }, { status: 400 });
836
- } catch (e17) {
927
+ } catch (e15) {
837
928
  }
838
929
  await _fs.promises.mkdir(folderPath, { recursive: true });
839
930
  return _server.NextResponse.json({ success: true, path: _path2.default.join(safePath, sanitizedName) });
@@ -861,13 +952,13 @@ async function handleRename(request) {
861
952
  }
862
953
  try {
863
954
  await _fs.promises.access(absoluteOldPath);
864
- } catch (e18) {
955
+ } catch (e16) {
865
956
  return _server.NextResponse.json({ error: "File or folder not found" }, { status: 404 });
866
957
  }
867
958
  try {
868
959
  await _fs.promises.access(absoluteNewPath);
869
960
  return _server.NextResponse.json({ error: "An item with this name already exists" }, { status: 400 });
870
- } catch (e19) {
961
+ } catch (e17) {
871
962
  }
872
963
  const stats = await _fs.promises.stat(absoluteOldPath);
873
964
  const isFile = stats.isFile();
@@ -889,7 +980,7 @@ async function handleRename(request) {
889
980
  await _fs.promises.mkdir(_path2.default.dirname(newThumbPath), { recursive: true });
890
981
  try {
891
982
  await _fs.promises.rename(oldThumbPath, newThumbPath);
892
- } catch (e20) {
983
+ } catch (e18) {
893
984
  }
894
985
  }
895
986
  delete meta[oldKey];
@@ -999,7 +1090,7 @@ async function handleMoveStream(request) {
999
1090
  await deleteFromCdn(oldKey, hasProcessedThumbnails);
1000
1091
  try {
1001
1092
  await _fs.promises.unlink(newAbsolutePath);
1002
- } catch (e21) {
1093
+ } catch (e19) {
1003
1094
  }
1004
1095
  if (hasProcessedThumbnails) {
1005
1096
  await deleteLocalThumbnails(newKey);
@@ -1016,7 +1107,7 @@ async function handleMoveStream(request) {
1016
1107
  }
1017
1108
  try {
1018
1109
  await _fs.promises.access(absolutePath);
1019
- } catch (e22) {
1110
+ } catch (e20) {
1020
1111
  errors.push(`${itemName} not found`);
1021
1112
  continue;
1022
1113
  }
@@ -1024,7 +1115,7 @@ async function handleMoveStream(request) {
1024
1115
  await _fs.promises.access(newAbsolutePath);
1025
1116
  errors.push(`${itemName} already exists in destination`);
1026
1117
  continue;
1027
- } catch (e23) {
1118
+ } catch (e21) {
1028
1119
  }
1029
1120
  await _fs.promises.rename(absolutePath, newAbsolutePath);
1030
1121
  const stats = await _fs.promises.stat(newAbsolutePath);
@@ -1037,7 +1128,7 @@ async function handleMoveStream(request) {
1037
1128
  await _fs.promises.mkdir(_path2.default.dirname(newThumbPath), { recursive: true });
1038
1129
  try {
1039
1130
  await _fs.promises.rename(oldThumbPath, newThumbPath);
1040
- } catch (e24) {
1131
+ } catch (e22) {
1041
1132
  }
1042
1133
  }
1043
1134
  delete meta[oldKey];
@@ -1142,7 +1233,7 @@ async function handleSync(request) {
1142
1233
  const originalLocalPath = _path2.default.join(process.cwd(), "public", imageKey);
1143
1234
  try {
1144
1235
  originalBuffer = await _fs.promises.readFile(originalLocalPath);
1145
- } catch (e25) {
1236
+ } catch (e23) {
1146
1237
  errors.push(`Original file not found: ${imageKey}`);
1147
1238
  continue;
1148
1239
  }
@@ -1170,7 +1261,7 @@ async function handleSync(request) {
1170
1261
  })
1171
1262
  );
1172
1263
  urlsToPurge.push(`${publicUrl}${thumbPath}`);
1173
- } catch (e26) {
1264
+ } catch (e24) {
1174
1265
  }
1175
1266
  }
1176
1267
  }
@@ -1181,12 +1272,12 @@ async function handleSync(request) {
1181
1272
  const localPath = _path2.default.join(process.cwd(), "public", thumbPath);
1182
1273
  try {
1183
1274
  await _fs.promises.unlink(localPath);
1184
- } catch (e27) {
1275
+ } catch (e25) {
1185
1276
  }
1186
1277
  }
1187
1278
  try {
1188
1279
  await _fs.promises.unlink(originalLocalPath);
1189
- } catch (e28) {
1280
+ } catch (e26) {
1190
1281
  }
1191
1282
  }
1192
1283
  pushed.push(imageKey);
@@ -1235,7 +1326,7 @@ async function handleReprocess(request) {
1235
1326
  const originalPath = _path2.default.join(process.cwd(), "public", imageKey);
1236
1327
  try {
1237
1328
  buffer = await _fs.promises.readFile(originalPath);
1238
- } catch (e29) {
1329
+ } catch (e27) {
1239
1330
  if (isInOurR2) {
1240
1331
  buffer = await downloadFromCdn(imageKey);
1241
1332
  const dir = _path2.default.dirname(originalPath);
@@ -1261,7 +1352,7 @@ async function handleReprocess(request) {
1261
1352
  await deleteLocalThumbnails(imageKey);
1262
1353
  try {
1263
1354
  await _fs.promises.unlink(originalPath);
1264
- } catch (e30) {
1355
+ } catch (e28) {
1265
1356
  }
1266
1357
  } else if (isRemote) {
1267
1358
  }
@@ -1381,7 +1472,7 @@ async function handleProcessAllStream() {
1381
1472
  await deleteLocalThumbnails(key);
1382
1473
  try {
1383
1474
  await _fs.promises.unlink(fullPath);
1384
- } catch (e31) {
1475
+ } catch (e29) {
1385
1476
  }
1386
1477
  }
1387
1478
  processed.push(key.slice(1));
@@ -1420,13 +1511,13 @@ async function handleProcessAllStream() {
1420
1511
  }
1421
1512
  }
1422
1513
  }
1423
- } catch (e32) {
1514
+ } catch (e30) {
1424
1515
  }
1425
1516
  }
1426
1517
  const imagesDir = _path2.default.join(process.cwd(), "public", "images");
1427
1518
  try {
1428
1519
  await findOrphans(imagesDir);
1429
- } catch (e33) {
1520
+ } catch (e31) {
1430
1521
  }
1431
1522
  async function removeEmptyDirs(dir) {
1432
1523
  try {
@@ -1444,13 +1535,13 @@ async function handleProcessAllStream() {
1444
1535
  await _fs.promises.rmdir(dir);
1445
1536
  }
1446
1537
  return isEmpty;
1447
- } catch (e34) {
1538
+ } catch (e32) {
1448
1539
  return true;
1449
1540
  }
1450
1541
  }
1451
1542
  try {
1452
1543
  await removeEmptyDirs(imagesDir);
1453
- } catch (e35) {
1544
+ } catch (e33) {
1454
1545
  }
1455
1546
  await saveMeta(meta);
1456
1547
  if (urlsToPurge.length > 0) {
@@ -1518,7 +1609,7 @@ async function handleScanStream() {
1518
1609
  allFiles.push({ relativePath: relPath, fullPath });
1519
1610
  }
1520
1611
  }
1521
- } catch (e36) {
1612
+ } catch (e34) {
1522
1613
  }
1523
1614
  }
1524
1615
  const publicDir = _path2.default.join(process.cwd(), "public");
@@ -1577,7 +1668,7 @@ async function handleScanStream() {
1577
1668
  o: { w: metadata.width || 0, h: metadata.height || 0 },
1578
1669
  b: blurhash
1579
1670
  };
1580
- } catch (e37) {
1671
+ } catch (e35) {
1581
1672
  meta[imageKey] = { o: { w: 0, h: 0 } };
1582
1673
  }
1583
1674
  }
@@ -1617,13 +1708,13 @@ async function handleScanStream() {
1617
1708
  }
1618
1709
  }
1619
1710
  }
1620
- } catch (e38) {
1711
+ } catch (e36) {
1621
1712
  }
1622
1713
  }
1623
1714
  const imagesDir = _path2.default.join(process.cwd(), "public", "images");
1624
1715
  try {
1625
1716
  await findOrphans(imagesDir);
1626
- } catch (e39) {
1717
+ } catch (e37) {
1627
1718
  }
1628
1719
  await saveMeta(meta);
1629
1720
  sendEvent({
@@ -1690,13 +1781,13 @@ async function handleDeleteOrphans(request) {
1690
1781
  await _fs.promises.rmdir(dir);
1691
1782
  }
1692
1783
  return isEmpty;
1693
- } catch (e40) {
1784
+ } catch (e38) {
1694
1785
  return true;
1695
1786
  }
1696
1787
  }
1697
1788
  try {
1698
1789
  await removeEmptyDirs(imagesDir);
1699
- } catch (e41) {
1790
+ } catch (e39) {
1700
1791
  }
1701
1792
  return _server.NextResponse.json({
1702
1793
  success: true,