@gallop.software/studio 2.3.26 → 2.3.28
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/client/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
12
12
|
}
|
|
13
13
|
</style>
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-OAEAClSN.js"></script>
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
package/dist/server/index.js
CHANGED
|
@@ -386,6 +386,20 @@ async function deleteThumbnailsFromCdn(imageKey) {
|
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
|
+
async function deleteOriginalFromCdn(imageKey) {
|
|
390
|
+
const bucketName = process.env.CLOUDFLARE_R2_BUCKET_NAME;
|
|
391
|
+
if (!bucketName) throw new Error("R2 bucket not configured");
|
|
392
|
+
const r2 = getR2Client();
|
|
393
|
+
try {
|
|
394
|
+
await r2.send(
|
|
395
|
+
new DeleteObjectCommand({
|
|
396
|
+
Bucket: bucketName,
|
|
397
|
+
Key: imageKey.replace(/^\//, "")
|
|
398
|
+
})
|
|
399
|
+
);
|
|
400
|
+
} catch {
|
|
401
|
+
}
|
|
402
|
+
}
|
|
389
403
|
|
|
390
404
|
// src/handlers/utils/response.ts
|
|
391
405
|
function jsonResponse(data, init) {
|
|
@@ -1258,6 +1272,7 @@ async function handleCreateFolder(request) {
|
|
|
1258
1272
|
}
|
|
1259
1273
|
}
|
|
1260
1274
|
async function handleRename(request) {
|
|
1275
|
+
const publicUrl = process.env.CLOUDFLARE_R2_PUBLIC_URL?.replace(/\/$/, "");
|
|
1261
1276
|
try {
|
|
1262
1277
|
const { oldPath, newName } = await request.json();
|
|
1263
1278
|
if (!oldPath || !newName) {
|
|
@@ -1268,48 +1283,109 @@ async function handleRename(request) {
|
|
|
1268
1283
|
if (!absoluteOldPath.startsWith(getPublicPath())) {
|
|
1269
1284
|
return jsonResponse({ error: "Invalid path" }, { status: 400 });
|
|
1270
1285
|
}
|
|
1286
|
+
const oldRelativePath = safePath.replace(/^public\//, "");
|
|
1287
|
+
const oldKey = "/" + oldRelativePath;
|
|
1288
|
+
const isImage = isImageFile(path6.basename(oldPath));
|
|
1289
|
+
const meta = await loadMeta();
|
|
1290
|
+
const cdnUrls = getCdnUrls(meta);
|
|
1291
|
+
const entry = meta[oldKey];
|
|
1292
|
+
const isInCloud = entry?.c !== void 0;
|
|
1293
|
+
const fileCdnUrl = isInCloud && entry.c !== void 0 ? cdnUrls[entry.c] : void 0;
|
|
1294
|
+
const isInOurR2 = isInCloud && fileCdnUrl === publicUrl;
|
|
1295
|
+
const hasThumbnails = entry ? isProcessed(entry) : false;
|
|
1296
|
+
let hasLocalFile = false;
|
|
1297
|
+
let isFile = true;
|
|
1271
1298
|
try {
|
|
1272
|
-
await fs6.
|
|
1299
|
+
const stats = await fs6.stat(absoluteOldPath);
|
|
1300
|
+
hasLocalFile = true;
|
|
1301
|
+
isFile = stats.isFile();
|
|
1273
1302
|
} catch {
|
|
1274
|
-
|
|
1303
|
+
if (!isInCloud) {
|
|
1304
|
+
return jsonResponse({ error: "File or folder not found" }, { status: 404 });
|
|
1305
|
+
}
|
|
1275
1306
|
}
|
|
1276
|
-
const stats = await fs6.stat(absoluteOldPath);
|
|
1277
|
-
const isFile = stats.isFile();
|
|
1278
|
-
const isImage = isFile && isImageFile(path6.basename(oldPath));
|
|
1279
1307
|
const sanitizedName = isFile ? slugifyFilename(newName) : slugifyFolderName(newName);
|
|
1280
1308
|
if (!sanitizedName) {
|
|
1281
1309
|
return jsonResponse({ error: "Invalid name" }, { status: 400 });
|
|
1282
1310
|
}
|
|
1283
1311
|
const parentDir = path6.dirname(absoluteOldPath);
|
|
1284
1312
|
const absoluteNewPath = path6.join(parentDir, sanitizedName);
|
|
1313
|
+
const newRelativePath = path6.join(path6.dirname(oldRelativePath), sanitizedName);
|
|
1314
|
+
const newKey = "/" + newRelativePath;
|
|
1315
|
+
if (meta[newKey]) {
|
|
1316
|
+
return jsonResponse({ error: "An item with this name already exists" }, { status: 400 });
|
|
1317
|
+
}
|
|
1285
1318
|
try {
|
|
1286
1319
|
await fs6.access(absoluteNewPath);
|
|
1287
1320
|
return jsonResponse({ error: "An item with this name already exists" }, { status: 400 });
|
|
1288
1321
|
} catch {
|
|
1289
1322
|
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
const oldKey = "/" + oldRelativePath;
|
|
1296
|
-
const newKey = "/" + newRelativePath;
|
|
1297
|
-
if (meta[oldKey]) {
|
|
1298
|
-
const entry = meta[oldKey];
|
|
1299
|
-
const oldThumbPaths = getAllThumbnailPaths(oldKey);
|
|
1323
|
+
if (isInOurR2 && !hasLocalFile && isImage) {
|
|
1324
|
+
const buffer = await downloadFromCdn(oldKey);
|
|
1325
|
+
await fs6.mkdir(path6.dirname(absoluteNewPath), { recursive: true });
|
|
1326
|
+
await fs6.writeFile(absoluteNewPath, buffer);
|
|
1327
|
+
if (hasThumbnails) {
|
|
1300
1328
|
const newThumbPaths = getAllThumbnailPaths(newKey);
|
|
1329
|
+
const oldThumbPaths = getAllThumbnailPaths(oldKey);
|
|
1301
1330
|
for (let i = 0; i < oldThumbPaths.length; i++) {
|
|
1302
|
-
const oldThumbPath = getPublicPath(oldThumbPaths[i]);
|
|
1303
|
-
const newThumbPath = getPublicPath(newThumbPaths[i]);
|
|
1304
|
-
await fs6.mkdir(path6.dirname(newThumbPath), { recursive: true });
|
|
1305
1331
|
try {
|
|
1306
|
-
await
|
|
1332
|
+
const thumbBuffer = await downloadFromCdn(oldThumbPaths[i]);
|
|
1333
|
+
const newThumbLocalPath = getPublicPath(newThumbPaths[i]);
|
|
1334
|
+
await fs6.mkdir(path6.dirname(newThumbLocalPath), { recursive: true });
|
|
1335
|
+
await fs6.writeFile(newThumbLocalPath, thumbBuffer);
|
|
1307
1336
|
} catch {
|
|
1308
1337
|
}
|
|
1309
1338
|
}
|
|
1310
|
-
delete meta[oldKey];
|
|
1311
|
-
meta[newKey] = entry;
|
|
1312
1339
|
}
|
|
1340
|
+
await deleteFromCdn(oldKey, hasThumbnails);
|
|
1341
|
+
await uploadOriginalToCdn(newKey);
|
|
1342
|
+
if (hasThumbnails) {
|
|
1343
|
+
await uploadToCdn(newKey);
|
|
1344
|
+
}
|
|
1345
|
+
try {
|
|
1346
|
+
await fs6.unlink(absoluteNewPath);
|
|
1347
|
+
} catch {
|
|
1348
|
+
}
|
|
1349
|
+
if (hasThumbnails) {
|
|
1350
|
+
await deleteLocalThumbnails(newKey);
|
|
1351
|
+
}
|
|
1352
|
+
delete meta[oldKey];
|
|
1353
|
+
meta[newKey] = entry;
|
|
1354
|
+
await saveMeta(meta);
|
|
1355
|
+
const newPath2 = path6.join(path6.dirname(safePath), sanitizedName);
|
|
1356
|
+
return jsonResponse({ success: true, newPath: newPath2 });
|
|
1357
|
+
}
|
|
1358
|
+
if (hasLocalFile) {
|
|
1359
|
+
await fs6.rename(absoluteOldPath, absoluteNewPath);
|
|
1360
|
+
}
|
|
1361
|
+
if (isImage && entry) {
|
|
1362
|
+
const oldThumbPaths = getAllThumbnailPaths(oldKey);
|
|
1363
|
+
const newThumbPaths = getAllThumbnailPaths(newKey);
|
|
1364
|
+
for (let i = 0; i < oldThumbPaths.length; i++) {
|
|
1365
|
+
const oldThumbPath = getPublicPath(oldThumbPaths[i]);
|
|
1366
|
+
const newThumbPath = getPublicPath(newThumbPaths[i]);
|
|
1367
|
+
await fs6.mkdir(path6.dirname(newThumbPath), { recursive: true });
|
|
1368
|
+
try {
|
|
1369
|
+
await fs6.rename(oldThumbPath, newThumbPath);
|
|
1370
|
+
} catch {
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
if (isInOurR2) {
|
|
1374
|
+
const buffer = await fs6.readFile(absoluteNewPath);
|
|
1375
|
+
await fs6.mkdir(path6.dirname(absoluteNewPath), { recursive: true });
|
|
1376
|
+
await deleteFromCdn(oldKey, hasThumbnails);
|
|
1377
|
+
await uploadOriginalToCdn(newKey);
|
|
1378
|
+
if (hasThumbnails) {
|
|
1379
|
+
await uploadToCdn(newKey);
|
|
1380
|
+
}
|
|
1381
|
+
try {
|
|
1382
|
+
await fs6.unlink(absoluteNewPath);
|
|
1383
|
+
} catch {
|
|
1384
|
+
}
|
|
1385
|
+
await deleteLocalThumbnails(newKey);
|
|
1386
|
+
}
|
|
1387
|
+
delete meta[oldKey];
|
|
1388
|
+
meta[newKey] = entry;
|
|
1313
1389
|
await saveMeta(meta);
|
|
1314
1390
|
}
|
|
1315
1391
|
const newPath = path6.join(path6.dirname(safePath), sanitizedName);
|
|
@@ -1914,7 +1990,9 @@ async function handleReprocessStream(request) {
|
|
|
1914
1990
|
const updatedEntry = await processImage(buffer, imageKey);
|
|
1915
1991
|
if (isInOurR2) {
|
|
1916
1992
|
updatedEntry.c = existingCdnIndex;
|
|
1993
|
+
await deleteOriginalFromCdn(imageKey);
|
|
1917
1994
|
await deleteThumbnailsFromCdn(imageKey);
|
|
1995
|
+
await uploadOriginalToCdn(imageKey);
|
|
1918
1996
|
await uploadToCdn(imageKey);
|
|
1919
1997
|
await deleteLocalThumbnails(imageKey);
|
|
1920
1998
|
try {
|