@gallop.software/studio 2.3.165 → 2.3.167
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/server/index.js +120 -20
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -2449,11 +2449,51 @@ async function handleDeleteStream(request) {
|
|
|
2449
2449
|
return;
|
|
2450
2450
|
}
|
|
2451
2451
|
const isCancelled = () => operationId ? isOperationCancelled(operationId) : false;
|
|
2452
|
+
async function countFilesInDir(dirPath) {
|
|
2453
|
+
let count = 0;
|
|
2454
|
+
try {
|
|
2455
|
+
const entries = await fs7.readdir(dirPath, { withFileTypes: true });
|
|
2456
|
+
for (const entry of entries) {
|
|
2457
|
+
if (entry.isDirectory()) {
|
|
2458
|
+
count += await countFilesInDir(path7.join(dirPath, entry.name));
|
|
2459
|
+
} else {
|
|
2460
|
+
count++;
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
} catch {
|
|
2464
|
+
}
|
|
2465
|
+
return count;
|
|
2466
|
+
}
|
|
2467
|
+
let totalFiles = 0;
|
|
2468
|
+
for (const itemPath of paths) {
|
|
2469
|
+
if (!itemPath.startsWith("public/")) continue;
|
|
2470
|
+
const absolutePath = getWorkspacePath(itemPath);
|
|
2471
|
+
try {
|
|
2472
|
+
const stats = await fs7.stat(absolutePath);
|
|
2473
|
+
if (stats.isDirectory()) {
|
|
2474
|
+
totalFiles += await countFilesInDir(absolutePath);
|
|
2475
|
+
} else {
|
|
2476
|
+
totalFiles++;
|
|
2477
|
+
}
|
|
2478
|
+
} catch {
|
|
2479
|
+
const imageKey = "/" + itemPath.replace(/^public\//, "");
|
|
2480
|
+
const meta2 = await loadMeta();
|
|
2481
|
+
const prefix = imageKey + "/";
|
|
2482
|
+
let count = 0;
|
|
2483
|
+
for (const key of Object.keys(meta2)) {
|
|
2484
|
+
if (key.startsWith(prefix) || key === imageKey) {
|
|
2485
|
+
count++;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
totalFiles += count || 1;
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2452
2491
|
const meta = await loadMeta();
|
|
2453
2492
|
const deleted = [];
|
|
2454
2493
|
const errors = [];
|
|
2455
2494
|
const sourceFolders = /* @__PURE__ */ new Set();
|
|
2456
|
-
const total = paths.length;
|
|
2495
|
+
const total = totalFiles || paths.length;
|
|
2496
|
+
let currentProgress = 0;
|
|
2457
2497
|
sendEvent({ type: "start", total });
|
|
2458
2498
|
for (let i = 0; i < paths.length; i++) {
|
|
2459
2499
|
if (isCancelled()) {
|
|
@@ -2476,12 +2516,13 @@ async function handleDeleteStream(request) {
|
|
|
2476
2516
|
try {
|
|
2477
2517
|
if (!itemPath.startsWith("public/")) {
|
|
2478
2518
|
errors.push(`Invalid path: ${itemPath}`);
|
|
2519
|
+
currentProgress++;
|
|
2479
2520
|
sendEvent({
|
|
2480
2521
|
type: "progress",
|
|
2481
|
-
current:
|
|
2522
|
+
current: currentProgress,
|
|
2482
2523
|
total,
|
|
2483
2524
|
deleted: deleted.length,
|
|
2484
|
-
percent: Math.round(
|
|
2525
|
+
percent: Math.round(currentProgress / total * 100),
|
|
2485
2526
|
currentFile: path7.basename(itemPath)
|
|
2486
2527
|
});
|
|
2487
2528
|
continue;
|
|
@@ -2495,6 +2536,7 @@ async function handleDeleteStream(request) {
|
|
|
2495
2536
|
try {
|
|
2496
2537
|
const stats = await fs7.stat(absolutePath);
|
|
2497
2538
|
if (stats.isDirectory()) {
|
|
2539
|
+
const filesInDir = await countFilesInDir(absolutePath);
|
|
2498
2540
|
await fs7.rm(absolutePath, { recursive: true });
|
|
2499
2541
|
const prefix = imageKey + "/";
|
|
2500
2542
|
for (const key of Object.keys(meta)) {
|
|
@@ -2518,6 +2560,7 @@ async function handleDeleteStream(request) {
|
|
|
2518
2560
|
delete meta[key];
|
|
2519
2561
|
}
|
|
2520
2562
|
}
|
|
2563
|
+
currentProgress += filesInDir || 1;
|
|
2521
2564
|
} else {
|
|
2522
2565
|
await fs7.unlink(absolutePath);
|
|
2523
2566
|
const isInImagesFolder = itemPath.startsWith("public/images/");
|
|
@@ -2538,6 +2581,7 @@ async function handleDeleteStream(request) {
|
|
|
2538
2581
|
}
|
|
2539
2582
|
delete meta[imageKey];
|
|
2540
2583
|
}
|
|
2584
|
+
currentProgress++;
|
|
2541
2585
|
}
|
|
2542
2586
|
} catch {
|
|
2543
2587
|
if (entry) {
|
|
@@ -2548,6 +2592,7 @@ async function handleDeleteStream(request) {
|
|
|
2548
2592
|
}
|
|
2549
2593
|
}
|
|
2550
2594
|
delete meta[imageKey];
|
|
2595
|
+
currentProgress++;
|
|
2551
2596
|
} else {
|
|
2552
2597
|
const prefix = imageKey + "/";
|
|
2553
2598
|
let foundAny = false;
|
|
@@ -2563,16 +2608,18 @@ async function handleDeleteStream(request) {
|
|
|
2563
2608
|
}
|
|
2564
2609
|
delete meta[key];
|
|
2565
2610
|
foundAny = true;
|
|
2611
|
+
currentProgress++;
|
|
2566
2612
|
}
|
|
2567
2613
|
}
|
|
2568
2614
|
if (!foundAny) {
|
|
2569
2615
|
errors.push(`Not found: ${itemPath}`);
|
|
2616
|
+
currentProgress++;
|
|
2570
2617
|
sendEvent({
|
|
2571
2618
|
type: "progress",
|
|
2572
|
-
current:
|
|
2619
|
+
current: currentProgress,
|
|
2573
2620
|
total,
|
|
2574
2621
|
deleted: deleted.length,
|
|
2575
|
-
percent: Math.round(
|
|
2622
|
+
percent: Math.round(currentProgress / total * 100),
|
|
2576
2623
|
currentFile: path7.basename(itemPath)
|
|
2577
2624
|
});
|
|
2578
2625
|
continue;
|
|
@@ -2587,10 +2634,10 @@ async function handleDeleteStream(request) {
|
|
|
2587
2634
|
}
|
|
2588
2635
|
sendEvent({
|
|
2589
2636
|
type: "progress",
|
|
2590
|
-
current:
|
|
2637
|
+
current: currentProgress,
|
|
2591
2638
|
total,
|
|
2592
2639
|
deleted: deleted.length,
|
|
2593
|
-
percent: Math.round(
|
|
2640
|
+
percent: Math.round(currentProgress / total * 100),
|
|
2594
2641
|
currentFile: path7.basename(itemPath)
|
|
2595
2642
|
});
|
|
2596
2643
|
}
|
|
@@ -4794,6 +4841,38 @@ async function handleFontsDeleteStream(request) {
|
|
|
4794
4841
|
return jsonResponse({ error: `Path not allowed: ${p}` }, { status: 400 });
|
|
4795
4842
|
}
|
|
4796
4843
|
}
|
|
4844
|
+
async function countFilesInDir(dirPath) {
|
|
4845
|
+
let count = 0;
|
|
4846
|
+
try {
|
|
4847
|
+
const entries = await fs12.readdir(dirPath, { withFileTypes: true });
|
|
4848
|
+
for (const entry of entries) {
|
|
4849
|
+
if (entry.isDirectory()) {
|
|
4850
|
+
count += await countFilesInDir(path11.join(dirPath, entry.name));
|
|
4851
|
+
} else {
|
|
4852
|
+
count++;
|
|
4853
|
+
}
|
|
4854
|
+
}
|
|
4855
|
+
} catch {
|
|
4856
|
+
}
|
|
4857
|
+
return count;
|
|
4858
|
+
}
|
|
4859
|
+
async function getFilesInDir(dirPath, basePath) {
|
|
4860
|
+
const files = [];
|
|
4861
|
+
try {
|
|
4862
|
+
const entries = await fs12.readdir(dirPath, { withFileTypes: true });
|
|
4863
|
+
for (const entry of entries) {
|
|
4864
|
+
const fullPath = path11.join(dirPath, entry.name);
|
|
4865
|
+
const relativePath = path11.join(basePath, entry.name);
|
|
4866
|
+
if (entry.isDirectory()) {
|
|
4867
|
+
files.push(...await getFilesInDir(fullPath, relativePath));
|
|
4868
|
+
} else {
|
|
4869
|
+
files.push(relativePath);
|
|
4870
|
+
}
|
|
4871
|
+
}
|
|
4872
|
+
} catch {
|
|
4873
|
+
}
|
|
4874
|
+
return files;
|
|
4875
|
+
}
|
|
4797
4876
|
const encoder = new TextEncoder();
|
|
4798
4877
|
const stream = new ReadableStream({
|
|
4799
4878
|
async start(controller) {
|
|
@@ -4802,29 +4881,50 @@ async function handleFontsDeleteStream(request) {
|
|
|
4802
4881
|
|
|
4803
4882
|
`));
|
|
4804
4883
|
};
|
|
4805
|
-
const
|
|
4806
|
-
const
|
|
4807
|
-
for (
|
|
4808
|
-
const
|
|
4809
|
-
const fileName = p.split("/").pop() || p;
|
|
4810
|
-
send({ status: "progress", message: `Deleting ${fileName}...`, current: i + 1, total: paths.length });
|
|
4811
|
-
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
4884
|
+
const allFiles = [];
|
|
4885
|
+
const foldersToDelete = [];
|
|
4886
|
+
for (const p of paths) {
|
|
4887
|
+
const fullPath = getWorkspacePath(p);
|
|
4812
4888
|
try {
|
|
4813
|
-
const fullPath = getWorkspacePath(p);
|
|
4814
4889
|
const stat = await fs12.stat(fullPath);
|
|
4815
4890
|
if (stat.isDirectory()) {
|
|
4816
|
-
|
|
4891
|
+
foldersToDelete.push(p);
|
|
4892
|
+
const filesInDir = await getFilesInDir(fullPath, p);
|
|
4893
|
+
for (const f of filesInDir) {
|
|
4894
|
+
allFiles.push({ path: f, isFolder: false, parentFolder: p });
|
|
4895
|
+
}
|
|
4817
4896
|
} else {
|
|
4818
|
-
|
|
4897
|
+
allFiles.push({ path: p, isFolder: false });
|
|
4819
4898
|
}
|
|
4820
|
-
|
|
4899
|
+
} catch {
|
|
4900
|
+
}
|
|
4901
|
+
}
|
|
4902
|
+
const total = allFiles.length;
|
|
4903
|
+
const deleted = [];
|
|
4904
|
+
const errors = [];
|
|
4905
|
+
let current = 0;
|
|
4906
|
+
for (const file of allFiles) {
|
|
4907
|
+
current++;
|
|
4908
|
+
const fileName = file.path.split("/").pop() || file.path;
|
|
4909
|
+
send({ status: "progress", message: `Deleting ${fileName}...`, current, total });
|
|
4910
|
+
try {
|
|
4911
|
+
const fullPath = getWorkspacePath(file.path);
|
|
4912
|
+
await fs12.unlink(fullPath);
|
|
4913
|
+
deleted.push(file.path);
|
|
4821
4914
|
} catch (err) {
|
|
4822
|
-
errors.push(`Failed to delete ${
|
|
4915
|
+
errors.push(`Failed to delete ${file.path}: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
4916
|
+
}
|
|
4917
|
+
}
|
|
4918
|
+
for (const folder of foldersToDelete) {
|
|
4919
|
+
try {
|
|
4920
|
+
const fullPath = getWorkspacePath(folder);
|
|
4921
|
+
await fs12.rm(fullPath, { recursive: true });
|
|
4922
|
+
} catch {
|
|
4823
4923
|
}
|
|
4824
4924
|
}
|
|
4825
4925
|
send({
|
|
4826
4926
|
status: "complete",
|
|
4827
|
-
message: `Deleted ${deleted.length}
|
|
4927
|
+
message: `Deleted ${deleted.length} file${deleted.length !== 1 ? "s" : ""}`,
|
|
4828
4928
|
deleted,
|
|
4829
4929
|
errors: errors.length > 0 ? errors : void 0
|
|
4830
4930
|
});
|