@gallop.software/studio 2.3.46 → 2.3.47

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.
@@ -208,7 +208,7 @@ async function processImage(buffer, imageKey) {
208
208
 
209
209
  // src/handlers/utils/cdn.ts
210
210
  import { promises as fs3 } from "fs";
211
- import { S3Client, GetObjectCommand, PutObjectCommand, DeleteObjectCommand } from "@aws-sdk/client-s3";
211
+ import { S3Client, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, CopyObjectCommand } from "@aws-sdk/client-s3";
212
212
 
213
213
  // src/types.ts
214
214
  function getThumbnailPath(originalPath, size) {
@@ -400,6 +400,34 @@ async function deleteOriginalFromCdn(imageKey) {
400
400
  } catch {
401
401
  }
402
402
  }
403
+ async function copyInCdn(oldKey, newKey) {
404
+ const bucketName = process.env.CLOUDFLARE_R2_BUCKET_NAME;
405
+ if (!bucketName) throw new Error("R2 bucket not configured");
406
+ const r2 = getR2Client();
407
+ const oldKeyClean = oldKey.replace(/^\//, "");
408
+ const newKeyClean = newKey.replace(/^\//, "");
409
+ await r2.send(
410
+ new CopyObjectCommand({
411
+ Bucket: bucketName,
412
+ CopySource: `${bucketName}/${oldKeyClean}`,
413
+ Key: newKeyClean
414
+ })
415
+ );
416
+ }
417
+ async function moveInCdn(oldKey, newKey, hasThumbnails) {
418
+ await copyInCdn(oldKey, newKey);
419
+ if (hasThumbnails) {
420
+ const oldThumbPaths = getAllThumbnailPaths(oldKey);
421
+ const newThumbPaths = getAllThumbnailPaths(newKey);
422
+ for (let i = 0; i < oldThumbPaths.length; i++) {
423
+ try {
424
+ await copyInCdn(oldThumbPaths[i], newThumbPaths[i]);
425
+ } catch {
426
+ }
427
+ }
428
+ }
429
+ await deleteFromCdn(oldKey, hasThumbnails);
430
+ }
403
431
 
404
432
  // src/handlers/utils/response.ts
405
433
  function jsonResponse(data, init) {
@@ -1811,35 +1839,7 @@ async function handleMoveStream(request) {
1811
1839
  let vItemMoved = false;
1812
1840
  if (isItemInR2) {
1813
1841
  try {
1814
- const itemLocalPath = getPublicPath(vItem.newKey);
1815
- const buffer = await downloadFromCdn(vItem.oldKey);
1816
- await fs6.mkdir(path6.dirname(itemLocalPath), { recursive: true });
1817
- await fs6.writeFile(itemLocalPath, buffer);
1818
- if (itemHasThumbnails) {
1819
- const oldThumbPaths = getAllThumbnailPaths(vItem.oldKey);
1820
- const newThumbPaths = getAllThumbnailPaths(vItem.newKey);
1821
- for (let t = 0; t < oldThumbPaths.length; t++) {
1822
- try {
1823
- const thumbBuffer = await downloadFromCdn(oldThumbPaths[t]);
1824
- const newThumbLocalPath = getPublicPath(newThumbPaths[t]);
1825
- await fs6.mkdir(path6.dirname(newThumbLocalPath), { recursive: true });
1826
- await fs6.writeFile(newThumbLocalPath, thumbBuffer);
1827
- } catch {
1828
- }
1829
- }
1830
- }
1831
- await deleteFromCdn(vItem.oldKey, itemHasThumbnails);
1832
- await uploadOriginalToCdn(vItem.newKey);
1833
- if (itemHasThumbnails) {
1834
- await uploadToCdn(vItem.newKey);
1835
- }
1836
- try {
1837
- await fs6.unlink(itemLocalPath);
1838
- } catch {
1839
- }
1840
- if (itemHasThumbnails) {
1841
- await deleteLocalThumbnails(vItem.newKey);
1842
- }
1842
+ await moveInCdn(vItem.oldKey, vItem.newKey, itemHasThumbnails);
1843
1843
  vItemMoved = true;
1844
1844
  } catch (err) {
1845
1845
  console.error(`Failed to move cloud item ${vItem.oldKey}:`, err);
@@ -1912,37 +1912,11 @@ async function handleMoveStream(request) {
1912
1912
  currentFile: itemName
1913
1913
  });
1914
1914
  } else if (isPushedToR2 && isImage) {
1915
- const buffer = await downloadFromCdn(oldKey);
1916
- await fs6.mkdir(path6.dirname(newAbsolutePath), { recursive: true });
1917
- await fs6.writeFile(newAbsolutePath, buffer);
1918
- let newEntry = {
1919
- o: entry?.o,
1920
- b: entry?.b
1921
- };
1922
- if (hasProcessedThumbnails) {
1923
- const processedEntry = await processImage(buffer, newKey);
1924
- newEntry = { ...newEntry, ...processedEntry };
1925
- }
1926
- await uploadOriginalToCdn(newKey);
1927
- if (hasProcessedThumbnails) {
1928
- await uploadToCdn(newKey);
1929
- }
1930
- await deleteFromCdn(oldKey, hasProcessedThumbnails);
1931
- try {
1932
- await fs6.unlink(newAbsolutePath);
1933
- } catch {
1934
- }
1935
- if (hasProcessedThumbnails) {
1936
- await deleteLocalThumbnails(newKey);
1937
- }
1938
- await deleteEmptyFolders(path6.dirname(newAbsolutePath));
1939
- if (hasProcessedThumbnails) {
1940
- const newThumbRelPath = newKey.slice(1);
1941
- await deleteEmptyFolders(path6.join(getPublicPath("images"), newThumbRelPath));
1942
- }
1943
- newEntry.c = entry?.c;
1915
+ await moveInCdn(oldKey, newKey, hasProcessedThumbnails);
1944
1916
  delete meta[oldKey];
1945
- meta[newKey] = newEntry;
1917
+ if (entry) {
1918
+ meta[newKey] = entry;
1919
+ }
1946
1920
  moved.push(itemPath);
1947
1921
  processedFiles++;
1948
1922
  sendEvent({
@@ -2100,11 +2074,7 @@ async function handleMoveStream(request) {
2100
2074
  const fileIsInR2 = fileIsInCloud && fileCdnUrl2 === r2PublicUrl;
2101
2075
  const fileHasThumbs = isProcessed(fileEntry);
2102
2076
  if (fileIsInR2) {
2103
- await deleteFromCdn(fileOldKey, fileHasThumbs);
2104
- await uploadOriginalToCdn(fileNewKey);
2105
- if (fileHasThumbs) {
2106
- await uploadToCdn(fileNewKey);
2107
- }
2077
+ await moveInCdn(fileOldKey, fileNewKey, fileHasThumbs);
2108
2078
  }
2109
2079
  delete meta[fileOldKey];
2110
2080
  meta[fileNewKey] = fileEntry;
@@ -2128,36 +2098,7 @@ async function handleMoveStream(request) {
2128
2098
  let cloudFileMoved = false;
2129
2099
  if (cloudIsInR2) {
2130
2100
  try {
2131
- const cloudLocalPath = getPublicPath(cloudFile.newKey);
2132
- const buffer = await downloadFromCdn(cloudFile.oldKey);
2133
- await fs6.mkdir(path6.dirname(cloudLocalPath), { recursive: true });
2134
- await fs6.writeFile(cloudLocalPath, buffer);
2135
- if (cloudHasThumbs) {
2136
- const oldThumbPaths = getAllThumbnailPaths(cloudFile.oldKey);
2137
- const newThumbPaths = getAllThumbnailPaths(cloudFile.newKey);
2138
- for (let t = 0; t < oldThumbPaths.length; t++) {
2139
- try {
2140
- const thumbBuffer = await downloadFromCdn(oldThumbPaths[t]);
2141
- const newThumbLocalPath = getPublicPath(newThumbPaths[t]);
2142
- await fs6.mkdir(path6.dirname(newThumbLocalPath), { recursive: true });
2143
- await fs6.writeFile(newThumbLocalPath, thumbBuffer);
2144
- } catch {
2145
- }
2146
- }
2147
- }
2148
- await deleteFromCdn(cloudFile.oldKey, cloudHasThumbs);
2149
- await uploadOriginalToCdn(cloudFile.newKey);
2150
- if (cloudHasThumbs) {
2151
- await uploadToCdn(cloudFile.newKey);
2152
- }
2153
- try {
2154
- await fs6.unlink(cloudLocalPath);
2155
- } catch {
2156
- }
2157
- if (cloudHasThumbs) {
2158
- await deleteLocalThumbnails(cloudFile.newKey);
2159
- }
2160
- await deleteEmptyFolders(path6.dirname(cloudLocalPath));
2101
+ await moveInCdn(cloudFile.oldKey, cloudFile.newKey, cloudHasThumbs);
2161
2102
  cloudFileMoved = true;
2162
2103
  } catch (err) {
2163
2104
  console.error(`Failed to move cloud file ${cloudFile.oldKey}:`, err);