@gallop.software/studio 0.1.71 → 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 = "") {
@@ -900,42 +816,16 @@ async function loadMeta() {
900
816
  const metaPath = _path2.default.join(process.cwd(), "_data", "_meta.json");
901
817
  try {
902
818
  const content = await _fs.promises.readFile(metaPath, "utf-8");
903
- const parsed = JSON.parse(content);
904
- if (parsed.images && typeof parsed.images === "object") {
905
- return parsed;
906
- }
907
- return {
908
- $schema: "https://gallop.software/schemas/studio-meta.json",
909
- version: 1,
910
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
911
- images: {}
912
- };
819
+ return JSON.parse(content);
913
820
  } catch (e18) {
914
- return {
915
- $schema: "https://gallop.software/schemas/studio-meta.json",
916
- version: 1,
917
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
918
- images: {}
919
- };
821
+ return {};
920
822
  }
921
823
  }
922
824
  async function saveMeta(meta) {
923
825
  const dataDir = _path2.default.join(process.cwd(), "_data");
924
826
  await _fs.promises.mkdir(dataDir, { recursive: true });
925
- const lean = {};
926
- for (const [key, entry] of Object.entries(meta.images)) {
927
- const imagePath = _optionalChain([entry, 'access', _13 => _13.original, 'optionalAccess', _14 => _14.path]) || `/${key}`;
928
- lean[imagePath] = {
929
- w: _optionalChain([entry, 'access', _15 => _15.original, 'optionalAccess', _16 => _16.width]) || 0,
930
- h: _optionalChain([entry, 'access', _17 => _17.original, 'optionalAccess', _18 => _18.height]) || 0,
931
- blur: entry.blurhash || ""
932
- };
933
- if (_optionalChain([entry, 'access', _19 => _19.cdn, 'optionalAccess', _20 => _20.synced])) {
934
- lean[imagePath].s = 1;
935
- }
936
- }
937
827
  const metaPath = _path2.default.join(dataDir, "_meta.json");
938
- await _fs.promises.writeFile(metaPath, JSON.stringify(lean, null, 2));
828
+ await _fs.promises.writeFile(metaPath, JSON.stringify(meta, null, 2));
939
829
  }
940
830
  function isImageFile(filename) {
941
831
  const ext = _path2.default.extname(filename).toLowerCase();
@@ -967,22 +857,17 @@ function getContentType(filePath) {
967
857
  return "application/octet-stream";
968
858
  }
969
859
  }
970
- async function processImage(buffer, entry, imageKey) {
860
+ async function processImage(buffer, imageKey) {
971
861
  const sharpInstance = _sharp2.default.call(void 0, buffer);
972
862
  const metadata = await sharpInstance.metadata();
973
863
  const originalWidth = metadata.width || 0;
974
864
  const originalHeight = metadata.height || 0;
975
- const baseName = _path2.default.basename(imageKey, _path2.default.extname(imageKey));
976
- const ext = _path2.default.extname(imageKey).toLowerCase();
977
- 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);
978
869
  const imagesPath = _path2.default.join(process.cwd(), "public", "images", imageDir === "." ? "" : imageDir);
979
870
  await _fs.promises.mkdir(imagesPath, { recursive: true });
980
- const sizes = {
981
- full: { path: "", width: originalWidth, height: originalHeight },
982
- large: { path: "", width: 0, height: 0 },
983
- medium: { path: "", width: 0, height: 0 },
984
- small: { path: "", width: 0, height: 0 }
985
- };
986
871
  const isPng = ext === ".png";
987
872
  const outputExt = isPng ? ".png" : ".jpg";
988
873
  const fullFileName = imageDir === "." ? `${baseName}${outputExt}` : `${imageDir}/${baseName}${outputExt}`;
@@ -992,11 +877,9 @@ async function processImage(buffer, entry, imageKey) {
992
877
  } else {
993
878
  await _sharp2.default.call(void 0, buffer).jpeg({ quality: 85 }).toFile(fullPath);
994
879
  }
995
- sizes.full.path = `/images/${fullFileName}`;
996
- for (const [sizeName, sizeConfig] of Object.entries(DEFAULT_SIZES)) {
880
+ for (const [, sizeConfig] of Object.entries(DEFAULT_SIZES)) {
997
881
  const { width: maxWidth, suffix } = sizeConfig;
998
882
  if (originalWidth <= maxWidth) {
999
- sizes[sizeName] = { ...sizes.full };
1000
883
  continue;
1001
884
  }
1002
885
  const ratio = originalHeight / originalWidth;
@@ -1009,27 +892,13 @@ async function processImage(buffer, entry, imageKey) {
1009
892
  } else {
1010
893
  await _sharp2.default.call(void 0, buffer).resize(maxWidth, newHeight).jpeg({ quality: 80 }).toFile(sizePath);
1011
894
  }
1012
- sizes[sizeName] = {
1013
- path: `/images/${sizeFilePath}`,
1014
- width: maxWidth,
1015
- height: newHeight
1016
- };
1017
895
  }
1018
896
  const { data, info } = await _sharp2.default.call(void 0, buffer).resize(32, 32, { fit: "inside" }).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
1019
897
  const blurhash = _blurhash.encode.call(void 0, new Uint8ClampedArray(data), info.width, info.height, 4, 4);
1020
- const { dominant } = await _sharp2.default.call(void 0, buffer).stats();
1021
- const dominantColor = `#${dominant.r.toString(16).padStart(2, "0")}${dominant.g.toString(16).padStart(2, "0")}${dominant.b.toString(16).padStart(2, "0")}`;
1022
898
  return {
1023
- ...entry,
1024
- original: {
1025
- ...entry.original,
1026
- width: originalWidth,
1027
- height: originalHeight,
1028
- fileSize: buffer.length
1029
- },
1030
- sizes,
1031
- blurhash,
1032
- dominantColor
899
+ w: originalWidth,
900
+ h: originalHeight,
901
+ blur: blurhash
1033
902
  };
1034
903
  }
1035
904
  async function downloadFromCdn(originalPath) {
@@ -1058,7 +927,7 @@ async function downloadFromCdn(originalPath) {
1058
927
  }
1059
928
  return Buffer.concat(chunks);
1060
929
  }
1061
- async function uploadToCdn(entry) {
930
+ async function uploadToCdn(imageKey) {
1062
931
  const accountId = process.env.CLOUDFLARE_R2_ACCOUNT_ID;
1063
932
  const accessKeyId = process.env.CLOUDFLARE_R2_ACCESS_KEY_ID;
1064
933
  const secretAccessKey = process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY;
@@ -1071,25 +940,28 @@ async function uploadToCdn(entry) {
1071
940
  endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
1072
941
  credentials: { accessKeyId, secretAccessKey }
1073
942
  });
1074
- for (const sizeData of Object.values(entry.sizes)) {
1075
- const localPath = _path2.default.join(process.cwd(), "public", sizeData.path);
1076
- const fileBuffer = await _fs.promises.readFile(localPath);
1077
- await r2.send(
1078
- new (0, _clients3.PutObjectCommand)({
1079
- Bucket: bucketName,
1080
- Key: sizeData.path.replace(/^\//, ""),
1081
- Body: fileBuffer,
1082
- ContentType: getContentType(sizeData.path)
1083
- })
1084
- );
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
+ }
1085
957
  }
1086
958
  }
1087
- async function deleteLocalFiles(entry) {
1088
- for (const sizeData of Object.values(entry.sizes)) {
1089
- 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);
1090
962
  try {
1091
963
  await _fs.promises.unlink(localPath);
1092
- } catch (e19) {
964
+ } catch (e20) {
1093
965
  }
1094
966
  }
1095
967
  }
@@ -1111,7 +983,7 @@ async function handleCreateFolder(request) {
1111
983
  try {
1112
984
  await _fs.promises.access(folderPath);
1113
985
  return _server.NextResponse.json({ error: "A folder with this name already exists" }, { status: 400 });
1114
- } catch (e20) {
986
+ } catch (e21) {
1115
987
  }
1116
988
  await _fs.promises.mkdir(folderPath, { recursive: true });
1117
989
  return _server.NextResponse.json({ success: true, path: _path2.default.join(safePath, sanitizedName) });
@@ -1139,13 +1011,13 @@ async function handleRename(request) {
1139
1011
  }
1140
1012
  try {
1141
1013
  await _fs.promises.access(absoluteOldPath);
1142
- } catch (e21) {
1014
+ } catch (e22) {
1143
1015
  return _server.NextResponse.json({ error: "File or folder not found" }, { status: 404 });
1144
1016
  }
1145
1017
  try {
1146
1018
  await _fs.promises.access(absoluteNewPath);
1147
1019
  return _server.NextResponse.json({ error: "An item with this name already exists" }, { status: 400 });
1148
- } catch (e22) {
1020
+ } catch (e23) {
1149
1021
  }
1150
1022
  const stats = await _fs.promises.stat(absoluteOldPath);
1151
1023
  const isFile = stats.isFile();
@@ -1155,32 +1027,23 @@ async function handleRename(request) {
1155
1027
  const meta = await loadMeta();
1156
1028
  const oldRelativePath = safePath.replace(/^public\//, "");
1157
1029
  const newRelativePath = _path2.default.join(_path2.default.dirname(oldRelativePath), sanitizedName);
1158
- for (const [key, entry] of Object.entries(meta.images)) {
1159
- if (entry.original.path === `/${oldRelativePath}`) {
1160
- entry.original.path = `/${newRelativePath}`;
1161
- const oldExt = _path2.default.extname(_path2.default.basename(oldPath));
1162
- const oldBaseName = _path2.default.basename(oldPath, oldExt);
1163
- const newExt = _path2.default.extname(sanitizedName);
1164
- const newBaseName = _path2.default.basename(sanitizedName, newExt);
1165
- const oldDirRelative = _path2.default.dirname(oldRelativePath);
1166
- const thumbnailDir = _path2.default.join(process.cwd(), "public", "images", oldDirRelative);
1167
- for (const [sizeName, sizeData] of Object.entries(entry.sizes)) {
1168
- const suffix = _optionalChain([DEFAULT_SIZES, 'access', _21 => _21[sizeName], 'optionalAccess', _22 => _22.suffix]) || `-${sizeName}`;
1169
- const oldThumbName = `${oldBaseName}${suffix}${oldExt === ".png" ? ".png" : ".jpg"}`;
1170
- const newThumbName = `${newBaseName}${suffix}${newExt === ".png" ? ".png" : ".jpg"}`;
1171
- const oldThumbPath = _path2.default.join(thumbnailDir, oldThumbName);
1172
- const newThumbPath = _path2.default.join(thumbnailDir, newThumbName);
1173
- try {
1174
- await _fs.promises.rename(oldThumbPath, newThumbPath);
1175
- sizeData.path = `/images/${oldDirRelative}/${newThumbName}`.replace(/\/+/g, "/");
1176
- } catch (e23) {
1177
- }
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) {
1178
1043
  }
1179
- const newKey = `/${newRelativePath}`;
1180
- delete meta.images[key];
1181
- meta.images[newKey] = entry;
1182
- break;
1183
1044
  }
1045
+ delete meta[oldKey];
1046
+ meta[newKey] = entry;
1184
1047
  }
1185
1048
  await saveMeta(meta);
1186
1049
  }
@@ -1213,7 +1076,7 @@ async function handleMove(request) {
1213
1076
  if (!destStats.isDirectory()) {
1214
1077
  return _server.NextResponse.json({ error: "Destination is not a folder" }, { status: 400 });
1215
1078
  }
1216
- } catch (e24) {
1079
+ } catch (e25) {
1217
1080
  return _server.NextResponse.json({ error: "Destination folder not found" }, { status: 404 });
1218
1081
  }
1219
1082
  const moved = [];
@@ -1231,7 +1094,7 @@ async function handleMove(request) {
1231
1094
  }
1232
1095
  try {
1233
1096
  await _fs.promises.access(absolutePath);
1234
- } catch (e25) {
1097
+ } catch (e26) {
1235
1098
  errors.push(`${itemName} not found`);
1236
1099
  continue;
1237
1100
  }
@@ -1239,7 +1102,7 @@ async function handleMove(request) {
1239
1102
  await _fs.promises.access(newAbsolutePath);
1240
1103
  errors.push(`${itemName} already exists in destination`);
1241
1104
  continue;
1242
- } catch (e26) {
1105
+ } catch (e27) {
1243
1106
  }
1244
1107
  try {
1245
1108
  await _fs.promises.rename(absolutePath, newAbsolutePath);
@@ -1247,33 +1110,24 @@ async function handleMove(request) {
1247
1110
  if (stats.isFile() && isImageFile(itemName)) {
1248
1111
  const oldRelativePath = safePath.replace(/^public\//, "");
1249
1112
  const newRelativePath = _path2.default.join(safeDestination.replace(/^public\//, ""), itemName);
1250
- for (const [key, entry] of Object.entries(meta.images)) {
1251
- if (entry.original.path === `/${oldRelativePath}`) {
1252
- entry.original.path = `/${newRelativePath}`;
1253
- const oldDir = _path2.default.dirname(oldRelativePath);
1254
- const newDir = _path2.default.dirname(newRelativePath);
1255
- const ext = _path2.default.extname(itemName);
1256
- const baseName = _path2.default.basename(itemName, ext);
1257
- const oldThumbDir = _path2.default.join(process.cwd(), "public", "images", oldDir);
1258
- const newThumbDir = _path2.default.join(process.cwd(), "public", "images", newDir);
1259
- await _fs.promises.mkdir(newThumbDir, { recursive: true });
1260
- for (const [sizeName, sizeData] of Object.entries(entry.sizes)) {
1261
- const suffix = _optionalChain([DEFAULT_SIZES, 'access', _23 => _23[sizeName], 'optionalAccess', _24 => _24.suffix]) || `-${sizeName}`;
1262
- const thumbName = `${baseName}${suffix}${ext === ".png" ? ".png" : ".jpg"}`;
1263
- const oldThumbPath = _path2.default.join(oldThumbDir, thumbName);
1264
- const newThumbPath = _path2.default.join(newThumbDir, thumbName);
1265
- try {
1266
- await _fs.promises.rename(oldThumbPath, newThumbPath);
1267
- sizeData.path = `/images/${newDir}/${thumbName}`.replace(/\/+/g, "/");
1268
- } catch (e27) {
1269
- }
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) {
1270
1126
  }
1271
- const newKey = `/${newRelativePath}`;
1272
- delete meta.images[key];
1273
- meta.images[newKey] = entry;
1274
- metaChanged = true;
1275
- break;
1276
1127
  }
1128
+ delete meta[oldKey];
1129
+ meta[newKey] = entry;
1130
+ metaChanged = true;
1277
1131
  }
1278
1132
  }
1279
1133
  moved.push(itemPath);
@@ -1313,7 +1167,7 @@ async function handleListFolders() {
1313
1167
  });
1314
1168
  await scanDir(_path2.default.join(dir, entry.name), folderRelativePath, depth + 1);
1315
1169
  }
1316
- } catch (e28) {
1170
+ } catch (e29) {
1317
1171
  }
1318
1172
  }
1319
1173
  folders.push({ path: "public", name: "public", depth: 0 });