@gallop.software/studio 0.1.72 → 0.1.73

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/dist/handlers.js CHANGED
@@ -1,4 +1,8 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/handlers.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+ var _chunkCN5NRNWBjs = require('./chunk-CN5NRNWB.js');
4
+
5
+ // src/handlers.ts
2
6
  var _server = require('next/server');
3
7
  var _fs = require('fs');
4
8
  var _path = require('path'); var _path2 = _interopRequireDefault(_path);
@@ -252,9 +256,9 @@ async function handleScan() {
252
256
  const validFiles = [];
253
257
  const imagesDir = _path2.default.join(process.cwd(), "public", "images");
254
258
  const trackedPaths = /* @__PURE__ */ new Set();
255
- for (const entry of Object.values(meta.images)) {
256
- for (const sizeData of Object.values(entry.sizes)) {
257
- trackedPaths.add(sizeData.path);
259
+ for (const imageKey of Object.keys(meta)) {
260
+ for (const thumbPath of _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, imageKey)) {
261
+ trackedPaths.add(thumbPath);
258
262
  }
259
263
  }
260
264
  async function scanDir(dir, relativePath = "") {
@@ -279,20 +283,20 @@ async function handleScan() {
279
283
  }
280
284
  }
281
285
  await scanDir(imagesDir);
282
- for (const [key, entry] of Object.entries(meta.images)) {
283
- for (const [size, sizeData] of Object.entries(entry.sizes)) {
284
- const filePath = _path2.default.join(process.cwd(), "public", sizeData.path);
286
+ for (const [imageKey, entry] of Object.entries(meta)) {
287
+ if (entry.s) continue;
288
+ for (const thumbPath of _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, imageKey)) {
289
+ const filePath = _path2.default.join(process.cwd(), "public", thumbPath);
285
290
  try {
286
291
  await _fs.promises.access(filePath);
287
292
  } catch (e8) {
288
- if (!_optionalChain([entry, 'access', _5 => _5.cdn, 'optionalAccess', _6 => _6.synced])) {
289
- missingFiles.push(`${key} (${size}): ${sizeData.path}`);
290
- }
293
+ missingFiles.push(`${imageKey}: ${thumbPath}`);
294
+ break;
291
295
  }
292
296
  }
293
297
  }
294
298
  return _server.NextResponse.json({
295
- totalInMeta: Object.keys(meta.images).length,
299
+ totalInMeta: Object.keys(meta).length,
296
300
  validFiles: validFiles.length,
297
301
  untrackedFiles,
298
302
  missingFiles
@@ -319,9 +323,6 @@ async function handleUpload(request) {
319
323
  const isSvg = ext === ".svg";
320
324
  const isProcessableImage = isImage && !isSvg;
321
325
  const meta = await loadMeta();
322
- if (!meta.images) {
323
- meta.images = {};
324
- }
325
326
  let relativeDir = "";
326
327
  if (targetPath === "public") {
327
328
  relativeDir = "";
@@ -344,10 +345,10 @@ async function handleUpload(request) {
344
345
  path: `public/${relativeDir ? relativeDir + "/" : ""}${fileName}`
345
346
  });
346
347
  }
347
- const fullImageKey = relativeDir ? `${relativeDir}/${fileName}` : fileName;
348
- if (meta.images[fullImageKey]) {
348
+ const imageKey = "/" + (relativeDir ? `${relativeDir}/${fileName}` : fileName);
349
+ if (meta[imageKey]) {
349
350
  return _server.NextResponse.json(
350
- { error: `File '${fullImageKey}' already exists in meta` },
351
+ { error: `File '${imageKey}' already exists in meta` },
351
352
  { status: 409 }
352
353
  );
353
354
  }
@@ -356,21 +357,10 @@ async function handleUpload(request) {
356
357
  let originalWidth = 0;
357
358
  let originalHeight = 0;
358
359
  let blurhash = "";
359
- let dominantColor = "#888888";
360
- const sizes = {
361
- full: { path: "", width: 0, height: 0 },
362
- large: { path: "", width: 0, height: 0 },
363
- medium: { path: "", width: 0, height: 0 },
364
- small: { path: "", width: 0, height: 0 }
365
- };
366
360
  const originalPath = `/${relativeDir ? relativeDir + "/" : ""}${fileName}`;
367
361
  if (isSvg) {
368
362
  const fullPath = _path2.default.join(imagesPath, fileName);
369
363
  await _fs.promises.writeFile(fullPath, buffer);
370
- sizes.full = { path: `/images/${relativeDir ? relativeDir + "/" : ""}${fileName}`, width: 0, height: 0 };
371
- sizes.large = { ...sizes.full };
372
- sizes.medium = { ...sizes.full };
373
- sizes.small = { ...sizes.full };
374
364
  } else if (isProcessableImage) {
375
365
  const sharpInstance = _sharp2.default.call(void 0, buffer);
376
366
  const metadata = await sharpInstance.metadata();
@@ -384,11 +374,9 @@ async function handleUpload(request) {
384
374
  } else {
385
375
  await _sharp2.default.call(void 0, buffer).jpeg({ quality: 85 }).toFile(fullPath);
386
376
  }
387
- sizes.full = { path: `/images/${relativeDir ? relativeDir + "/" : ""}${fullFileName}`, width: originalWidth, height: originalHeight };
388
- for (const [sizeName, sizeConfig] of Object.entries(DEFAULT_SIZES)) {
377
+ for (const [, sizeConfig] of Object.entries(DEFAULT_SIZES)) {
389
378
  const { width: maxWidth, suffix } = sizeConfig;
390
379
  if (originalWidth <= maxWidth) {
391
- sizes[sizeName] = { ...sizes.full };
392
380
  continue;
393
381
  }
394
382
  const ratio = originalHeight / originalWidth;
@@ -400,32 +388,18 @@ async function handleUpload(request) {
400
388
  } else {
401
389
  await _sharp2.default.call(void 0, buffer).resize(maxWidth, newHeight).jpeg({ quality: 80 }).toFile(sizePath);
402
390
  }
403
- sizes[sizeName] = {
404
- path: `/images/${relativeDir ? relativeDir + "/" : ""}${sizeFileName}`,
405
- width: maxWidth,
406
- height: newHeight
407
- };
408
391
  }
409
392
  const { data, info } = await _sharp2.default.call(void 0, buffer).resize(32, 32, { fit: "inside" }).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
410
393
  blurhash = _blurhash.encode.call(void 0, new Uint8ClampedArray(data), info.width, info.height, 4, 4);
411
- const { dominant } = await _sharp2.default.call(void 0, buffer).stats();
412
- dominantColor = `#${dominant.r.toString(16).padStart(2, "0")}${dominant.g.toString(16).padStart(2, "0")}${dominant.b.toString(16).padStart(2, "0")}`;
413
394
  }
414
395
  const entry = {
415
- original: {
416
- path: originalPath,
417
- width: originalWidth,
418
- height: originalHeight,
419
- fileSize: buffer.length
420
- },
421
- sizes,
422
- blurhash,
423
- dominantColor,
424
- cdn: null
396
+ w: originalWidth,
397
+ h: originalHeight,
398
+ blur: blurhash
425
399
  };
426
- meta.images[fullImageKey] = entry;
400
+ meta[originalPath] = entry;
427
401
  await saveMeta(meta);
428
- return _server.NextResponse.json({ success: true, imageKey: fullImageKey, entry });
402
+ return _server.NextResponse.json({ success: true, imageKey: originalPath, entry });
429
403
  } catch (error) {
430
404
  console.error("Failed to upload:", error);
431
405
  const message = error instanceof Error ? error.message : "Unknown error";
@@ -451,27 +425,26 @@ async function handleDelete(request) {
451
425
  const stats = await _fs.promises.stat(absolutePath);
452
426
  if (stats.isDirectory()) {
453
427
  await _fs.promises.rm(absolutePath, { recursive: true });
454
- const prefix = itemPath.replace(/^public\/images\/?/, "").replace(/^public\/?/, "");
455
- for (const key of Object.keys(meta.images)) {
428
+ const prefix = "/" + itemPath.replace(/^public\/images\/?/, "").replace(/^public\/?/, "");
429
+ for (const key of Object.keys(meta)) {
456
430
  if (key.startsWith(prefix)) {
457
- delete meta.images[key];
431
+ delete meta[key];
458
432
  }
459
433
  }
460
434
  } else {
461
435
  await _fs.promises.unlink(absolutePath);
462
436
  const isInImagesFolder = itemPath.startsWith("public/images/");
463
437
  if (!isInImagesFolder) {
464
- const imageKey = itemPath.replace(/^public\//, "");
465
- const entry = meta.images[imageKey];
466
- if (entry) {
467
- for (const sizeData of Object.values(entry.sizes)) {
468
- const sizePath = _path2.default.join(process.cwd(), "public", sizeData.path);
438
+ const imageKey = "/" + itemPath.replace(/^public\//, "");
439
+ if (meta[imageKey]) {
440
+ for (const thumbPath of _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, imageKey)) {
441
+ const absoluteThumbPath = _path2.default.join(process.cwd(), "public", thumbPath);
469
442
  try {
470
- await _fs.promises.unlink(sizePath);
443
+ await _fs.promises.unlink(absoluteThumbPath);
471
444
  } catch (e9) {
472
445
  }
473
446
  }
474
- delete meta.images[imageKey];
447
+ delete meta[imageKey];
475
448
  }
476
449
  }
477
450
  }
@@ -518,38 +491,37 @@ async function handleSync(request) {
518
491
  const synced = [];
519
492
  const errors = [];
520
493
  for (const imageKey of imageKeys) {
521
- const entry = meta.images[imageKey];
494
+ const entry = meta[imageKey];
522
495
  if (!entry) {
523
496
  errors.push(`Image not found in meta: ${imageKey}`);
524
497
  continue;
525
498
  }
526
- if (_optionalChain([entry, 'access', _7 => _7.cdn, 'optionalAccess', _8 => _8.synced])) {
499
+ if (entry.s) {
527
500
  synced.push(imageKey);
528
501
  continue;
529
502
  }
530
503
  try {
531
- for (const sizeData of Object.values(entry.sizes)) {
532
- const localPath = _path2.default.join(process.cwd(), "public", sizeData.path);
533
- const fileBuffer = await _fs.promises.readFile(localPath);
534
- await r2.send(
535
- new (0, _clients3.PutObjectCommand)({
536
- Bucket: bucketName,
537
- Key: sizeData.path.replace(/^\//, ""),
538
- Body: fileBuffer,
539
- ContentType: getContentType(sizeData.path)
540
- })
541
- );
504
+ for (const thumbPath of _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, imageKey)) {
505
+ const localPath = _path2.default.join(process.cwd(), "public", thumbPath);
506
+ try {
507
+ const fileBuffer = await _fs.promises.readFile(localPath);
508
+ await r2.send(
509
+ new (0, _clients3.PutObjectCommand)({
510
+ Bucket: bucketName,
511
+ Key: thumbPath.replace(/^\//, ""),
512
+ Body: fileBuffer,
513
+ ContentType: getContentType(thumbPath)
514
+ })
515
+ );
516
+ } catch (e10) {
517
+ }
542
518
  }
543
- entry.cdn = {
544
- synced: true,
545
- baseUrl: publicUrl,
546
- syncedAt: (/* @__PURE__ */ new Date()).toISOString()
547
- };
548
- for (const sizeData of Object.values(entry.sizes)) {
549
- const localPath = _path2.default.join(process.cwd(), "public", sizeData.path);
519
+ entry.s = 1;
520
+ for (const thumbPath of _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, imageKey)) {
521
+ const localPath = _path2.default.join(process.cwd(), "public", thumbPath);
550
522
  try {
551
523
  await _fs.promises.unlink(localPath);
552
- } catch (e10) {
524
+ } catch (e11) {
553
525
  }
554
526
  }
555
527
  synced.push(imageKey);
@@ -581,54 +553,24 @@ async function handleReprocess(request) {
581
553
  for (const imageKey of imageKeys) {
582
554
  try {
583
555
  let buffer;
584
- let entry = meta.images[imageKey];
556
+ const entry = meta[imageKey];
585
557
  const originalPath = _path2.default.join(process.cwd(), "public", imageKey);
586
558
  try {
587
559
  buffer = await _fs.promises.readFile(originalPath);
588
- } catch (e11) {
589
- if (entry) {
590
- const entryOriginalPath = _path2.default.join(process.cwd(), "public", entry.original.path);
591
- try {
592
- buffer = await _fs.promises.readFile(entryOriginalPath);
593
- } catch (e12) {
594
- if (_optionalChain([entry, 'access', _9 => _9.cdn, 'optionalAccess', _10 => _10.synced])) {
595
- buffer = await downloadFromCdn(entry.original.path);
596
- } else {
597
- throw new Error("Original not found locally and not on CDN");
598
- }
599
- }
560
+ } catch (e12) {
561
+ if (_optionalChain([entry, 'optionalAccess', _5 => _5.s])) {
562
+ buffer = await downloadFromCdn(imageKey);
600
563
  } else {
601
564
  throw new Error(`File not found: ${imageKey}`);
602
565
  }
603
566
  }
604
- if (!entry) {
605
- const sharpInstance = _sharp2.default.call(void 0, buffer);
606
- const metadata = await sharpInstance.metadata();
607
- const stats = await _fs.promises.stat(originalPath);
608
- entry = {
609
- original: {
610
- path: imageKey,
611
- width: metadata.width || 0,
612
- height: metadata.height || 0,
613
- fileSize: stats.size
614
- },
615
- sizes: {
616
- full: { path: "", width: 0, height: 0 },
617
- large: { path: "", width: 0, height: 0 },
618
- medium: { path: "", width: 0, height: 0 },
619
- small: { path: "", width: 0, height: 0 }
620
- },
621
- blurhash: "",
622
- dominantColor: "#000000",
623
- cdn: null
624
- };
625
- }
626
- const updatedEntry = await processImage(buffer, entry, imageKey);
627
- meta.images[imageKey] = updatedEntry;
628
- if (_optionalChain([entry, 'access', _11 => _11.cdn, 'optionalAccess', _12 => _12.synced])) {
629
- await uploadToCdn(updatedEntry);
630
- await deleteLocalFiles(updatedEntry);
567
+ const updatedEntry = await processImage(buffer, imageKey);
568
+ if (_optionalChain([entry, 'optionalAccess', _6 => _6.s])) {
569
+ updatedEntry.s = 1;
570
+ await uploadToCdn(imageKey);
571
+ await deleteLocalThumbnails(imageKey);
631
572
  }
573
+ meta[imageKey] = updatedEntry;
632
574
  processed.push(imageKey);
633
575
  } catch (error) {
634
576
  console.error(`Failed to reprocess ${imageKey}:`, error);
@@ -755,6 +697,7 @@ async function handleProcessAllStream() {
755
697
  sendEvent({ type: "start", total });
756
698
  for (let i = 0; i < allImages.length; i++) {
757
699
  const { key, fullPath } = allImages[i];
700
+ const imageKey = "/" + key;
758
701
  sendEvent({
759
702
  type: "progress",
760
703
  current: i + 1,
@@ -773,45 +716,18 @@ async function handleProcessAllStream() {
773
716
  const fileName = _path2.default.basename(key);
774
717
  const destPath = _path2.default.join(imagesPath, fileName);
775
718
  await _fs.promises.writeFile(destPath, buffer);
776
- const sizePath = `/images/${imageDir === "." ? "" : imageDir + "/"}${fileName}`;
777
- meta.images[key] = {
778
- original: {
779
- path: `/${key}`,
780
- width: 0,
781
- height: 0,
782
- fileSize: buffer.length
783
- },
784
- sizes: {
785
- full: { path: sizePath, width: 0, height: 0 },
786
- large: { path: sizePath, width: 0, height: 0 },
787
- medium: { path: sizePath, width: 0, height: 0 },
788
- small: { path: sizePath, width: 0, height: 0 }
789
- },
790
- blurhash: "",
791
- dominantColor: "#888888",
792
- cdn: null
719
+ meta[imageKey] = {
720
+ w: 0,
721
+ h: 0,
722
+ blur: ""
793
723
  };
794
724
  } else {
795
- const existingEntry = meta.images[key];
796
- const baseEntry = existingEntry || {
797
- original: {
798
- path: `/${key}`,
799
- width: 0,
800
- height: 0,
801
- fileSize: buffer.length
802
- },
803
- sizes: {
804
- full: { path: "", width: 0, height: 0 },
805
- large: { path: "", width: 0, height: 0 },
806
- medium: { path: "", width: 0, height: 0 },
807
- small: { path: "", width: 0, height: 0 }
808
- },
809
- blurhash: "",
810
- dominantColor: "#888888",
811
- cdn: null
812
- };
813
- const processedEntry = await processImage(buffer, baseEntry, key);
814
- meta.images[key] = processedEntry;
725
+ const existingEntry = meta[imageKey];
726
+ const processedEntry = await processImage(buffer, imageKey);
727
+ if (_optionalChain([existingEntry, 'optionalAccess', _7 => _7.s])) {
728
+ processedEntry.s = 1;
729
+ }
730
+ meta[imageKey] = processedEntry;
815
731
  }
816
732
  processed.push(key);
817
733
  } catch (error) {
@@ -821,9 +737,9 @@ async function handleProcessAllStream() {
821
737
  }
822
738
  sendEvent({ type: "cleanup", message: "Removing orphaned thumbnails..." });
823
739
  const trackedPaths = /* @__PURE__ */ new Set();
824
- for (const entry of Object.values(meta.images)) {
825
- for (const sizeData of Object.values(entry.sizes)) {
826
- trackedPaths.add(sizeData.path);
740
+ for (const imageKey of Object.keys(meta)) {
741
+ for (const thumbPath of _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, imageKey)) {
742
+ trackedPaths.add(thumbPath);
827
743
  }
828
744
  }
829
745
  async function findOrphans(dir, relativePath = "") {
@@ -898,57 +814,18 @@ async function handleProcessAllStream() {
898
814
  }
899
815
  async function loadMeta() {
900
816
  const metaPath = _path2.default.join(process.cwd(), "_data", "_meta.json");
901
- const emptyMeta = {
902
- $schema: "https://gallop.software/schemas/studio-meta.json",
903
- version: 1,
904
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
905
- images: {}
906
- };
907
817
  try {
908
818
  const content = await _fs.promises.readFile(metaPath, "utf-8");
909
- const parsed = JSON.parse(content);
910
- if (parsed.images && typeof parsed.images === "object") {
911
- return parsed;
912
- }
913
- const meta = { ...emptyMeta, images: {} };
914
- for (const [imagePath, entry] of Object.entries(parsed)) {
915
- const leanEntry = entry;
916
- const key = imagePath.startsWith("/") ? imagePath.slice(1) : imagePath;
917
- meta.images[key] = {
918
- original: {
919
- path: imagePath,
920
- width: leanEntry.w,
921
- height: leanEntry.h,
922
- fileSize: 0
923
- },
924
- sizes: {},
925
- blurhash: leanEntry.blur,
926
- dominantColor: "",
927
- cdn: leanEntry.s ? { synced: true, baseUrl: "", syncedAt: "" } : null
928
- };
929
- }
930
- return meta;
819
+ return JSON.parse(content);
931
820
  } catch (e18) {
932
- return emptyMeta;
821
+ return {};
933
822
  }
934
823
  }
935
824
  async function saveMeta(meta) {
936
825
  const dataDir = _path2.default.join(process.cwd(), "_data");
937
826
  await _fs.promises.mkdir(dataDir, { recursive: true });
938
- const lean = {};
939
- for (const [key, entry] of Object.entries(meta.images)) {
940
- const imagePath = _optionalChain([entry, 'access', _13 => _13.original, 'optionalAccess', _14 => _14.path]) || `/${key}`;
941
- lean[imagePath] = {
942
- w: _optionalChain([entry, 'access', _15 => _15.original, 'optionalAccess', _16 => _16.width]) || 0,
943
- h: _optionalChain([entry, 'access', _17 => _17.original, 'optionalAccess', _18 => _18.height]) || 0,
944
- blur: entry.blurhash || ""
945
- };
946
- if (_optionalChain([entry, 'access', _19 => _19.cdn, 'optionalAccess', _20 => _20.synced])) {
947
- lean[imagePath].s = 1;
948
- }
949
- }
950
827
  const metaPath = _path2.default.join(dataDir, "_meta.json");
951
- await _fs.promises.writeFile(metaPath, JSON.stringify(lean, null, 2));
828
+ await _fs.promises.writeFile(metaPath, JSON.stringify(meta, null, 2));
952
829
  }
953
830
  function isImageFile(filename) {
954
831
  const ext = _path2.default.extname(filename).toLowerCase();
@@ -980,22 +857,17 @@ function getContentType(filePath) {
980
857
  return "application/octet-stream";
981
858
  }
982
859
  }
983
- async function processImage(buffer, entry, imageKey) {
860
+ async function processImage(buffer, imageKey) {
984
861
  const sharpInstance = _sharp2.default.call(void 0, buffer);
985
862
  const metadata = await sharpInstance.metadata();
986
863
  const originalWidth = metadata.width || 0;
987
864
  const originalHeight = metadata.height || 0;
988
- const baseName = _path2.default.basename(imageKey, _path2.default.extname(imageKey));
989
- const ext = _path2.default.extname(imageKey).toLowerCase();
990
- const imageDir = _path2.default.dirname(imageKey);
865
+ const keyWithoutSlash = imageKey.startsWith("/") ? imageKey.slice(1) : imageKey;
866
+ const baseName = _path2.default.basename(keyWithoutSlash, _path2.default.extname(keyWithoutSlash));
867
+ const ext = _path2.default.extname(keyWithoutSlash).toLowerCase();
868
+ const imageDir = _path2.default.dirname(keyWithoutSlash);
991
869
  const imagesPath = _path2.default.join(process.cwd(), "public", "images", imageDir === "." ? "" : imageDir);
992
870
  await _fs.promises.mkdir(imagesPath, { recursive: true });
993
- const sizes = {
994
- full: { path: "", width: originalWidth, height: originalHeight },
995
- large: { path: "", width: 0, height: 0 },
996
- medium: { path: "", width: 0, height: 0 },
997
- small: { path: "", width: 0, height: 0 }
998
- };
999
871
  const isPng = ext === ".png";
1000
872
  const outputExt = isPng ? ".png" : ".jpg";
1001
873
  const fullFileName = imageDir === "." ? `${baseName}${outputExt}` : `${imageDir}/${baseName}${outputExt}`;
@@ -1005,11 +877,9 @@ async function processImage(buffer, entry, imageKey) {
1005
877
  } else {
1006
878
  await _sharp2.default.call(void 0, buffer).jpeg({ quality: 85 }).toFile(fullPath);
1007
879
  }
1008
- sizes.full.path = `/images/${fullFileName}`;
1009
- for (const [sizeName, sizeConfig] of Object.entries(DEFAULT_SIZES)) {
880
+ for (const [, sizeConfig] of Object.entries(DEFAULT_SIZES)) {
1010
881
  const { width: maxWidth, suffix } = sizeConfig;
1011
882
  if (originalWidth <= maxWidth) {
1012
- sizes[sizeName] = { ...sizes.full };
1013
883
  continue;
1014
884
  }
1015
885
  const ratio = originalHeight / originalWidth;
@@ -1022,27 +892,13 @@ async function processImage(buffer, entry, imageKey) {
1022
892
  } else {
1023
893
  await _sharp2.default.call(void 0, buffer).resize(maxWidth, newHeight).jpeg({ quality: 80 }).toFile(sizePath);
1024
894
  }
1025
- sizes[sizeName] = {
1026
- path: `/images/${sizeFilePath}`,
1027
- width: maxWidth,
1028
- height: newHeight
1029
- };
1030
895
  }
1031
896
  const { data, info } = await _sharp2.default.call(void 0, buffer).resize(32, 32, { fit: "inside" }).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
1032
897
  const blurhash = _blurhash.encode.call(void 0, new Uint8ClampedArray(data), info.width, info.height, 4, 4);
1033
- const { dominant } = await _sharp2.default.call(void 0, buffer).stats();
1034
- const dominantColor = `#${dominant.r.toString(16).padStart(2, "0")}${dominant.g.toString(16).padStart(2, "0")}${dominant.b.toString(16).padStart(2, "0")}`;
1035
898
  return {
1036
- ...entry,
1037
- original: {
1038
- ...entry.original,
1039
- width: originalWidth,
1040
- height: originalHeight,
1041
- fileSize: buffer.length
1042
- },
1043
- sizes,
1044
- blurhash,
1045
- dominantColor
899
+ w: originalWidth,
900
+ h: originalHeight,
901
+ blur: blurhash
1046
902
  };
1047
903
  }
1048
904
  async function downloadFromCdn(originalPath) {
@@ -1071,7 +927,7 @@ async function downloadFromCdn(originalPath) {
1071
927
  }
1072
928
  return Buffer.concat(chunks);
1073
929
  }
1074
- async function uploadToCdn(entry) {
930
+ async function uploadToCdn(imageKey) {
1075
931
  const accountId = process.env.CLOUDFLARE_R2_ACCOUNT_ID;
1076
932
  const accessKeyId = process.env.CLOUDFLARE_R2_ACCESS_KEY_ID;
1077
933
  const secretAccessKey = process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY;
@@ -1084,25 +940,28 @@ async function uploadToCdn(entry) {
1084
940
  endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
1085
941
  credentials: { accessKeyId, secretAccessKey }
1086
942
  });
1087
- for (const sizeData of Object.values(entry.sizes)) {
1088
- const localPath = _path2.default.join(process.cwd(), "public", sizeData.path);
1089
- const fileBuffer = await _fs.promises.readFile(localPath);
1090
- await r2.send(
1091
- new (0, _clients3.PutObjectCommand)({
1092
- Bucket: bucketName,
1093
- Key: sizeData.path.replace(/^\//, ""),
1094
- Body: fileBuffer,
1095
- ContentType: getContentType(sizeData.path)
1096
- })
1097
- );
943
+ for (const thumbPath of _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, imageKey)) {
944
+ const localPath = _path2.default.join(process.cwd(), "public", thumbPath);
945
+ try {
946
+ const fileBuffer = await _fs.promises.readFile(localPath);
947
+ await r2.send(
948
+ new (0, _clients3.PutObjectCommand)({
949
+ Bucket: bucketName,
950
+ Key: thumbPath.replace(/^\//, ""),
951
+ Body: fileBuffer,
952
+ ContentType: getContentType(thumbPath)
953
+ })
954
+ );
955
+ } catch (e19) {
956
+ }
1098
957
  }
1099
958
  }
1100
- async function deleteLocalFiles(entry) {
1101
- for (const sizeData of Object.values(entry.sizes)) {
1102
- const localPath = _path2.default.join(process.cwd(), "public", sizeData.path);
959
+ async function deleteLocalThumbnails(imageKey) {
960
+ for (const thumbPath of _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, imageKey)) {
961
+ const localPath = _path2.default.join(process.cwd(), "public", thumbPath);
1103
962
  try {
1104
963
  await _fs.promises.unlink(localPath);
1105
- } catch (e19) {
964
+ } catch (e20) {
1106
965
  }
1107
966
  }
1108
967
  }
@@ -1124,7 +983,7 @@ async function handleCreateFolder(request) {
1124
983
  try {
1125
984
  await _fs.promises.access(folderPath);
1126
985
  return _server.NextResponse.json({ error: "A folder with this name already exists" }, { status: 400 });
1127
- } catch (e20) {
986
+ } catch (e21) {
1128
987
  }
1129
988
  await _fs.promises.mkdir(folderPath, { recursive: true });
1130
989
  return _server.NextResponse.json({ success: true, path: _path2.default.join(safePath, sanitizedName) });
@@ -1152,13 +1011,13 @@ async function handleRename(request) {
1152
1011
  }
1153
1012
  try {
1154
1013
  await _fs.promises.access(absoluteOldPath);
1155
- } catch (e21) {
1014
+ } catch (e22) {
1156
1015
  return _server.NextResponse.json({ error: "File or folder not found" }, { status: 404 });
1157
1016
  }
1158
1017
  try {
1159
1018
  await _fs.promises.access(absoluteNewPath);
1160
1019
  return _server.NextResponse.json({ error: "An item with this name already exists" }, { status: 400 });
1161
- } catch (e22) {
1020
+ } catch (e23) {
1162
1021
  }
1163
1022
  const stats = await _fs.promises.stat(absoluteOldPath);
1164
1023
  const isFile = stats.isFile();
@@ -1168,32 +1027,23 @@ async function handleRename(request) {
1168
1027
  const meta = await loadMeta();
1169
1028
  const oldRelativePath = safePath.replace(/^public\//, "");
1170
1029
  const newRelativePath = _path2.default.join(_path2.default.dirname(oldRelativePath), sanitizedName);
1171
- for (const [key, entry] of Object.entries(meta.images)) {
1172
- if (entry.original.path === `/${oldRelativePath}`) {
1173
- entry.original.path = `/${newRelativePath}`;
1174
- const oldExt = _path2.default.extname(_path2.default.basename(oldPath));
1175
- const oldBaseName = _path2.default.basename(oldPath, oldExt);
1176
- const newExt = _path2.default.extname(sanitizedName);
1177
- const newBaseName = _path2.default.basename(sanitizedName, newExt);
1178
- const oldDirRelative = _path2.default.dirname(oldRelativePath);
1179
- const thumbnailDir = _path2.default.join(process.cwd(), "public", "images", oldDirRelative);
1180
- for (const [sizeName, sizeData] of Object.entries(entry.sizes)) {
1181
- const suffix = _optionalChain([DEFAULT_SIZES, 'access', _21 => _21[sizeName], 'optionalAccess', _22 => _22.suffix]) || `-${sizeName}`;
1182
- const oldThumbName = `${oldBaseName}${suffix}${oldExt === ".png" ? ".png" : ".jpg"}`;
1183
- const newThumbName = `${newBaseName}${suffix}${newExt === ".png" ? ".png" : ".jpg"}`;
1184
- const oldThumbPath = _path2.default.join(thumbnailDir, oldThumbName);
1185
- const newThumbPath = _path2.default.join(thumbnailDir, newThumbName);
1186
- try {
1187
- await _fs.promises.rename(oldThumbPath, newThumbPath);
1188
- sizeData.path = `/images/${oldDirRelative}/${newThumbName}`.replace(/\/+/g, "/");
1189
- } catch (e23) {
1190
- }
1030
+ const oldKey = "/" + oldRelativePath;
1031
+ const newKey = "/" + newRelativePath;
1032
+ if (meta[oldKey]) {
1033
+ const entry = meta[oldKey];
1034
+ const oldThumbPaths = _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, oldKey);
1035
+ const newThumbPaths = _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, newKey);
1036
+ for (let i = 0; i < oldThumbPaths.length; i++) {
1037
+ const oldThumbPath = _path2.default.join(process.cwd(), "public", oldThumbPaths[i]);
1038
+ const newThumbPath = _path2.default.join(process.cwd(), "public", newThumbPaths[i]);
1039
+ await _fs.promises.mkdir(_path2.default.dirname(newThumbPath), { recursive: true });
1040
+ try {
1041
+ await _fs.promises.rename(oldThumbPath, newThumbPath);
1042
+ } catch (e24) {
1191
1043
  }
1192
- const newKey = `/${newRelativePath}`;
1193
- delete meta.images[key];
1194
- meta.images[newKey] = entry;
1195
- break;
1196
1044
  }
1045
+ delete meta[oldKey];
1046
+ meta[newKey] = entry;
1197
1047
  }
1198
1048
  await saveMeta(meta);
1199
1049
  }
@@ -1226,7 +1076,7 @@ async function handleMove(request) {
1226
1076
  if (!destStats.isDirectory()) {
1227
1077
  return _server.NextResponse.json({ error: "Destination is not a folder" }, { status: 400 });
1228
1078
  }
1229
- } catch (e24) {
1079
+ } catch (e25) {
1230
1080
  return _server.NextResponse.json({ error: "Destination folder not found" }, { status: 404 });
1231
1081
  }
1232
1082
  const moved = [];
@@ -1244,7 +1094,7 @@ async function handleMove(request) {
1244
1094
  }
1245
1095
  try {
1246
1096
  await _fs.promises.access(absolutePath);
1247
- } catch (e25) {
1097
+ } catch (e26) {
1248
1098
  errors.push(`${itemName} not found`);
1249
1099
  continue;
1250
1100
  }
@@ -1252,7 +1102,7 @@ async function handleMove(request) {
1252
1102
  await _fs.promises.access(newAbsolutePath);
1253
1103
  errors.push(`${itemName} already exists in destination`);
1254
1104
  continue;
1255
- } catch (e26) {
1105
+ } catch (e27) {
1256
1106
  }
1257
1107
  try {
1258
1108
  await _fs.promises.rename(absolutePath, newAbsolutePath);
@@ -1260,33 +1110,24 @@ async function handleMove(request) {
1260
1110
  if (stats.isFile() && isImageFile(itemName)) {
1261
1111
  const oldRelativePath = safePath.replace(/^public\//, "");
1262
1112
  const newRelativePath = _path2.default.join(safeDestination.replace(/^public\//, ""), itemName);
1263
- for (const [key, entry] of Object.entries(meta.images)) {
1264
- if (entry.original.path === `/${oldRelativePath}`) {
1265
- entry.original.path = `/${newRelativePath}`;
1266
- const oldDir = _path2.default.dirname(oldRelativePath);
1267
- const newDir = _path2.default.dirname(newRelativePath);
1268
- const ext = _path2.default.extname(itemName);
1269
- const baseName = _path2.default.basename(itemName, ext);
1270
- const oldThumbDir = _path2.default.join(process.cwd(), "public", "images", oldDir);
1271
- const newThumbDir = _path2.default.join(process.cwd(), "public", "images", newDir);
1272
- await _fs.promises.mkdir(newThumbDir, { recursive: true });
1273
- for (const [sizeName, sizeData] of Object.entries(entry.sizes)) {
1274
- const suffix = _optionalChain([DEFAULT_SIZES, 'access', _23 => _23[sizeName], 'optionalAccess', _24 => _24.suffix]) || `-${sizeName}`;
1275
- const thumbName = `${baseName}${suffix}${ext === ".png" ? ".png" : ".jpg"}`;
1276
- const oldThumbPath = _path2.default.join(oldThumbDir, thumbName);
1277
- const newThumbPath = _path2.default.join(newThumbDir, thumbName);
1278
- try {
1279
- await _fs.promises.rename(oldThumbPath, newThumbPath);
1280
- sizeData.path = `/images/${newDir}/${thumbName}`.replace(/\/+/g, "/");
1281
- } catch (e27) {
1282
- }
1113
+ const oldKey = "/" + oldRelativePath;
1114
+ const newKey = "/" + newRelativePath;
1115
+ if (meta[oldKey]) {
1116
+ const entry = meta[oldKey];
1117
+ const oldThumbPaths = _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, oldKey);
1118
+ const newThumbPaths = _chunkCN5NRNWBjs.getAllThumbnailPaths.call(void 0, newKey);
1119
+ for (let i = 0; i < oldThumbPaths.length; i++) {
1120
+ const oldThumbPath = _path2.default.join(process.cwd(), "public", oldThumbPaths[i]);
1121
+ const newThumbPath = _path2.default.join(process.cwd(), "public", newThumbPaths[i]);
1122
+ await _fs.promises.mkdir(_path2.default.dirname(newThumbPath), { recursive: true });
1123
+ try {
1124
+ await _fs.promises.rename(oldThumbPath, newThumbPath);
1125
+ } catch (e28) {
1283
1126
  }
1284
- const newKey = `/${newRelativePath}`;
1285
- delete meta.images[key];
1286
- meta.images[newKey] = entry;
1287
- metaChanged = true;
1288
- break;
1289
1127
  }
1128
+ delete meta[oldKey];
1129
+ meta[newKey] = entry;
1130
+ metaChanged = true;
1290
1131
  }
1291
1132
  }
1292
1133
  moved.push(itemPath);
@@ -1326,7 +1167,7 @@ async function handleListFolders() {
1326
1167
  });
1327
1168
  await scanDir(_path2.default.join(dir, entry.name), folderRelativePath, depth + 1);
1328
1169
  }
1329
- } catch (e28) {
1170
+ } catch (e29) {
1330
1171
  }
1331
1172
  }
1332
1173
  folders.push({ path: "public", name: "public", depth: 0 });