@gallop.software/studio 2.3.65 → 2.3.67
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-CVpv3I0V.js"></script>
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
package/dist/server/index.js
CHANGED
|
@@ -2278,6 +2278,197 @@ async function handleDelete(request) {
|
|
|
2278
2278
|
return jsonResponse({ error: "Failed to delete files" }, { status: 500 });
|
|
2279
2279
|
}
|
|
2280
2280
|
}
|
|
2281
|
+
async function handleDeleteStream(request) {
|
|
2282
|
+
const encoder = new TextEncoder();
|
|
2283
|
+
const stream = new ReadableStream({
|
|
2284
|
+
async start(controller) {
|
|
2285
|
+
const sendEvent = (data) => {
|
|
2286
|
+
try {
|
|
2287
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}
|
|
2288
|
+
|
|
2289
|
+
`));
|
|
2290
|
+
} catch {
|
|
2291
|
+
}
|
|
2292
|
+
};
|
|
2293
|
+
try {
|
|
2294
|
+
const { paths, operationId } = await request.json();
|
|
2295
|
+
if (!paths || !Array.isArray(paths) || paths.length === 0) {
|
|
2296
|
+
sendEvent({ type: "error", message: "No paths provided" });
|
|
2297
|
+
controller.close();
|
|
2298
|
+
return;
|
|
2299
|
+
}
|
|
2300
|
+
const isCancelled = () => operationId ? isOperationCancelled(operationId) : false;
|
|
2301
|
+
const meta = await loadMeta();
|
|
2302
|
+
const deleted = [];
|
|
2303
|
+
const errors = [];
|
|
2304
|
+
const sourceFolders = /* @__PURE__ */ new Set();
|
|
2305
|
+
const total = paths.length;
|
|
2306
|
+
sendEvent({ type: "start", total });
|
|
2307
|
+
for (let i = 0; i < paths.length; i++) {
|
|
2308
|
+
if (isCancelled()) {
|
|
2309
|
+
await saveMeta(meta);
|
|
2310
|
+
for (const folder of sourceFolders) {
|
|
2311
|
+
await deleteEmptyFolders(folder);
|
|
2312
|
+
}
|
|
2313
|
+
if (operationId) clearCancelledOperation(operationId);
|
|
2314
|
+
sendEvent({
|
|
2315
|
+
type: "complete",
|
|
2316
|
+
deleted: deleted.length,
|
|
2317
|
+
errors: errors.length,
|
|
2318
|
+
message: `Stopped. Deleted ${deleted.length} item${deleted.length !== 1 ? "s" : ""}.`,
|
|
2319
|
+
cancelled: true
|
|
2320
|
+
});
|
|
2321
|
+
controller.close();
|
|
2322
|
+
return;
|
|
2323
|
+
}
|
|
2324
|
+
const itemPath = paths[i];
|
|
2325
|
+
try {
|
|
2326
|
+
if (!itemPath.startsWith("public/")) {
|
|
2327
|
+
errors.push(`Invalid path: ${itemPath}`);
|
|
2328
|
+
sendEvent({
|
|
2329
|
+
type: "progress",
|
|
2330
|
+
current: i + 1,
|
|
2331
|
+
total,
|
|
2332
|
+
deleted: deleted.length,
|
|
2333
|
+
percent: Math.round((i + 1) / total * 100),
|
|
2334
|
+
currentFile: path7.basename(itemPath)
|
|
2335
|
+
});
|
|
2336
|
+
continue;
|
|
2337
|
+
}
|
|
2338
|
+
const absolutePath = getWorkspacePath(itemPath);
|
|
2339
|
+
const imageKey = "/" + itemPath.replace(/^public\//, "");
|
|
2340
|
+
sourceFolders.add(path7.dirname(absolutePath));
|
|
2341
|
+
const entry = meta[imageKey];
|
|
2342
|
+
const isPushedToCloud = entry?.c !== void 0;
|
|
2343
|
+
const hasThumbnails = entry ? isProcessed(entry) : false;
|
|
2344
|
+
try {
|
|
2345
|
+
const stats = await fs7.stat(absolutePath);
|
|
2346
|
+
if (stats.isDirectory()) {
|
|
2347
|
+
await fs7.rm(absolutePath, { recursive: true });
|
|
2348
|
+
const prefix = imageKey + "/";
|
|
2349
|
+
for (const key of Object.keys(meta)) {
|
|
2350
|
+
if (key.startsWith(prefix) || key === imageKey) {
|
|
2351
|
+
const keyEntry = meta[key];
|
|
2352
|
+
const keyHasThumbnails = keyEntry ? isProcessed(keyEntry) : false;
|
|
2353
|
+
if (keyEntry?.c !== void 0) {
|
|
2354
|
+
try {
|
|
2355
|
+
await deleteFromCdn(key, keyHasThumbnails);
|
|
2356
|
+
} catch {
|
|
2357
|
+
}
|
|
2358
|
+
} else {
|
|
2359
|
+
for (const thumbPath of getAllThumbnailPaths(key)) {
|
|
2360
|
+
const absoluteThumbPath = getPublicPath(thumbPath);
|
|
2361
|
+
try {
|
|
2362
|
+
await fs7.unlink(absoluteThumbPath);
|
|
2363
|
+
} catch {
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
delete meta[key];
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
} else {
|
|
2371
|
+
await fs7.unlink(absolutePath);
|
|
2372
|
+
const isInImagesFolder = itemPath.startsWith("public/images/");
|
|
2373
|
+
if (!isInImagesFolder && entry) {
|
|
2374
|
+
if (isPushedToCloud) {
|
|
2375
|
+
try {
|
|
2376
|
+
await deleteFromCdn(imageKey, hasThumbnails);
|
|
2377
|
+
} catch {
|
|
2378
|
+
}
|
|
2379
|
+
} else {
|
|
2380
|
+
for (const thumbPath of getAllThumbnailPaths(imageKey)) {
|
|
2381
|
+
const absoluteThumbPath = getPublicPath(thumbPath);
|
|
2382
|
+
try {
|
|
2383
|
+
await fs7.unlink(absoluteThumbPath);
|
|
2384
|
+
} catch {
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
delete meta[imageKey];
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
} catch {
|
|
2392
|
+
if (entry) {
|
|
2393
|
+
if (isPushedToCloud) {
|
|
2394
|
+
try {
|
|
2395
|
+
await deleteFromCdn(imageKey, hasThumbnails);
|
|
2396
|
+
} catch {
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
delete meta[imageKey];
|
|
2400
|
+
} else {
|
|
2401
|
+
const prefix = imageKey + "/";
|
|
2402
|
+
let foundAny = false;
|
|
2403
|
+
for (const key of Object.keys(meta)) {
|
|
2404
|
+
if (key.startsWith(prefix)) {
|
|
2405
|
+
const keyEntry = meta[key];
|
|
2406
|
+
const keyHasThumbnails = keyEntry ? isProcessed(keyEntry) : false;
|
|
2407
|
+
if (keyEntry?.c !== void 0) {
|
|
2408
|
+
try {
|
|
2409
|
+
await deleteFromCdn(key, keyHasThumbnails);
|
|
2410
|
+
} catch {
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
delete meta[key];
|
|
2414
|
+
foundAny = true;
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
if (!foundAny) {
|
|
2418
|
+
errors.push(`Not found: ${itemPath}`);
|
|
2419
|
+
sendEvent({
|
|
2420
|
+
type: "progress",
|
|
2421
|
+
current: i + 1,
|
|
2422
|
+
total,
|
|
2423
|
+
deleted: deleted.length,
|
|
2424
|
+
percent: Math.round((i + 1) / total * 100),
|
|
2425
|
+
currentFile: path7.basename(itemPath)
|
|
2426
|
+
});
|
|
2427
|
+
continue;
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
await saveMeta(meta);
|
|
2432
|
+
deleted.push(itemPath);
|
|
2433
|
+
} catch (error) {
|
|
2434
|
+
console.error(`Failed to delete ${itemPath}:`, error);
|
|
2435
|
+
errors.push(itemPath);
|
|
2436
|
+
}
|
|
2437
|
+
sendEvent({
|
|
2438
|
+
type: "progress",
|
|
2439
|
+
current: i + 1,
|
|
2440
|
+
total,
|
|
2441
|
+
deleted: deleted.length,
|
|
2442
|
+
percent: Math.round((i + 1) / total * 100),
|
|
2443
|
+
currentFile: path7.basename(itemPath)
|
|
2444
|
+
});
|
|
2445
|
+
}
|
|
2446
|
+
for (const folder of sourceFolders) {
|
|
2447
|
+
await deleteEmptyFolders(folder);
|
|
2448
|
+
}
|
|
2449
|
+
if (operationId) clearCancelledOperation(operationId);
|
|
2450
|
+
sendEvent({
|
|
2451
|
+
type: "complete",
|
|
2452
|
+
deleted: deleted.length,
|
|
2453
|
+
errors: errors.length,
|
|
2454
|
+
errorMessages: errors.length > 0 ? errors : void 0
|
|
2455
|
+
});
|
|
2456
|
+
} catch (error) {
|
|
2457
|
+
console.error("Failed to delete:", error);
|
|
2458
|
+
sendEvent({ type: "error", message: "Failed to delete files" });
|
|
2459
|
+
} finally {
|
|
2460
|
+
controller.close();
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
});
|
|
2464
|
+
return new Response(stream, {
|
|
2465
|
+
headers: {
|
|
2466
|
+
"Content-Type": "text/event-stream",
|
|
2467
|
+
"Cache-Control": "no-cache",
|
|
2468
|
+
"Connection": "keep-alive"
|
|
2469
|
+
}
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2281
2472
|
async function handleCreateFolder(request) {
|
|
2282
2473
|
try {
|
|
2283
2474
|
const { parentPath, name } = await request.json();
|
|
@@ -3795,6 +3986,7 @@ async function startServer(options) {
|
|
|
3795
3986
|
app.post("/api/studio/cdns", wrapHandler(handleUpdateCdns));
|
|
3796
3987
|
app.post("/api/studio/generate-favicon", wrapHandler(handleGenerateFavicon, true));
|
|
3797
3988
|
app.post("/api/studio/delete", wrapHandler(handleDelete));
|
|
3989
|
+
app.post("/api/studio/delete-stream", wrapHandler(handleDeleteStream, true));
|
|
3798
3990
|
app.use(express.static(join(workspace, "public")));
|
|
3799
3991
|
const clientDir = resolve(__dirname, "../client");
|
|
3800
3992
|
app.get("/", (req, res) => {
|