@gallop.software/studio 2.3.42 → 2.3.44
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 +179 -57
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -1841,6 +1841,10 @@ async function handleMoveStream(request) {
|
|
|
1841
1841
|
currentFile: path6.basename(vItem.newKey)
|
|
1842
1842
|
});
|
|
1843
1843
|
}
|
|
1844
|
+
const newFolderPath = getPublicPath(newKey);
|
|
1845
|
+
await deleteEmptyFolders(newFolderPath);
|
|
1846
|
+
const newThumbFolder = path6.join(getPublicPath("images"), newKey.slice(1));
|
|
1847
|
+
await deleteEmptyFolders(newThumbFolder);
|
|
1844
1848
|
moved.push(itemPath);
|
|
1845
1849
|
continue;
|
|
1846
1850
|
}
|
|
@@ -1912,6 +1916,11 @@ async function handleMoveStream(request) {
|
|
|
1912
1916
|
if (hasProcessedThumbnails) {
|
|
1913
1917
|
await deleteLocalThumbnails(newKey);
|
|
1914
1918
|
}
|
|
1919
|
+
await deleteEmptyFolders(path6.dirname(newAbsolutePath));
|
|
1920
|
+
if (hasProcessedThumbnails) {
|
|
1921
|
+
const newThumbRelPath = newKey.slice(1);
|
|
1922
|
+
await deleteEmptyFolders(path6.join(getPublicPath("images"), newThumbRelPath));
|
|
1923
|
+
}
|
|
1915
1924
|
newEntry.c = entry?.c;
|
|
1916
1925
|
delete meta[oldKey];
|
|
1917
1926
|
meta[newKey] = newEntry;
|
|
@@ -1970,74 +1979,187 @@ async function handleMoveStream(request) {
|
|
|
1970
1979
|
continue;
|
|
1971
1980
|
} catch {
|
|
1972
1981
|
}
|
|
1973
|
-
await fs6.
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
const
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1982
|
+
const stats = await fs6.stat(absolutePath);
|
|
1983
|
+
if (stats.isFile()) {
|
|
1984
|
+
await fs6.mkdir(path6.dirname(newAbsolutePath), { recursive: true });
|
|
1985
|
+
await fs6.rename(absolutePath, newAbsolutePath);
|
|
1986
|
+
if (isImage && entry) {
|
|
1987
|
+
const oldThumbPaths = getAllThumbnailPaths(oldKey);
|
|
1988
|
+
const newThumbPaths = getAllThumbnailPaths(newKey);
|
|
1989
|
+
for (let j = 0; j < oldThumbPaths.length; j++) {
|
|
1990
|
+
const oldThumbPath = getPublicPath(oldThumbPaths[j]);
|
|
1991
|
+
const newThumbPath = getPublicPath(newThumbPaths[j]);
|
|
1992
|
+
try {
|
|
1993
|
+
await fs6.access(oldThumbPath);
|
|
1994
|
+
sourceFolders.add(path6.dirname(oldThumbPath));
|
|
1995
|
+
await fs6.mkdir(path6.dirname(newThumbPath), { recursive: true });
|
|
1996
|
+
await fs6.rename(oldThumbPath, newThumbPath);
|
|
1997
|
+
} catch {
|
|
1998
|
+
}
|
|
1987
1999
|
}
|
|
2000
|
+
const fileIsInCloud = entry.c !== void 0;
|
|
2001
|
+
const fileCdnUrl2 = fileIsInCloud ? cdnUrls[entry.c] : void 0;
|
|
2002
|
+
const fileIsInR2 = fileIsInCloud && fileCdnUrl2 === r2PublicUrl;
|
|
2003
|
+
const fileHasThumbs = isProcessed(entry);
|
|
2004
|
+
if (fileIsInR2) {
|
|
2005
|
+
await deleteFromCdn(oldKey, fileHasThumbs);
|
|
2006
|
+
await uploadOriginalToCdn(newKey);
|
|
2007
|
+
if (fileHasThumbs) {
|
|
2008
|
+
await uploadToCdn(newKey);
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
delete meta[oldKey];
|
|
2012
|
+
meta[newKey] = entry;
|
|
1988
2013
|
}
|
|
1989
|
-
|
|
1990
|
-
|
|
2014
|
+
processedFiles++;
|
|
2015
|
+
sendEvent({
|
|
2016
|
+
type: "progress",
|
|
2017
|
+
current: processedFiles,
|
|
2018
|
+
total: totalFiles,
|
|
2019
|
+
moved: moved.length,
|
|
2020
|
+
percent: Math.round(processedFiles / totalFiles * 100),
|
|
2021
|
+
currentFile: itemName
|
|
2022
|
+
});
|
|
2023
|
+
moved.push(itemPath);
|
|
1991
2024
|
} else if (stats.isDirectory()) {
|
|
1992
2025
|
const oldPrefix = oldKey + "/";
|
|
1993
2026
|
const newPrefix = newKey + "/";
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
const newMetaKey = newPrefix + key.slice(oldPrefix.length);
|
|
1997
|
-
meta[newMetaKey] = meta[key];
|
|
1998
|
-
delete meta[key];
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
const oldThumbRelPath = oldKey.slice(1);
|
|
2002
|
-
const newThumbRelPath = newKey.slice(1);
|
|
2003
|
-
const imagesDir = getPublicPath("images");
|
|
2004
|
-
const oldThumbFolder = path6.join(imagesDir, oldThumbRelPath);
|
|
2005
|
-
const newThumbFolder = path6.join(imagesDir, newThumbRelPath);
|
|
2006
|
-
try {
|
|
2007
|
-
await fs6.access(oldThumbFolder);
|
|
2008
|
-
sourceFolders.add(oldThumbFolder);
|
|
2009
|
-
await fs6.mkdir(path6.dirname(newThumbFolder), { recursive: true });
|
|
2010
|
-
await fs6.rename(oldThumbFolder, newThumbFolder);
|
|
2011
|
-
} catch {
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
moved.push(itemPath);
|
|
2015
|
-
if (stats.isDirectory()) {
|
|
2016
|
-
const countFilesInDir = async (dir) => {
|
|
2017
|
-
let count = 0;
|
|
2027
|
+
const localFiles = [];
|
|
2028
|
+
const collectLocalFiles = async (dir, relativeDir) => {
|
|
2018
2029
|
const entries = await fs6.readdir(dir, { withFileTypes: true });
|
|
2019
|
-
for (const
|
|
2020
|
-
|
|
2021
|
-
|
|
2030
|
+
for (const dirEntry of entries) {
|
|
2031
|
+
const entryRelPath = relativeDir ? `${relativeDir}/${dirEntry.name}` : dirEntry.name;
|
|
2032
|
+
if (dirEntry.isDirectory()) {
|
|
2033
|
+
await collectLocalFiles(path6.join(dir, dirEntry.name), entryRelPath);
|
|
2022
2034
|
} else {
|
|
2023
|
-
|
|
2035
|
+
localFiles.push({ relativePath: entryRelPath, isImage: isImageFile(dirEntry.name) });
|
|
2024
2036
|
}
|
|
2025
2037
|
}
|
|
2026
|
-
return count;
|
|
2027
2038
|
};
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2039
|
+
await collectLocalFiles(absolutePath, "");
|
|
2040
|
+
const cloudOnlyFiles = [];
|
|
2041
|
+
for (const [metaKey, metaEntry] of Object.entries(meta)) {
|
|
2042
|
+
if (metaKey.startsWith(oldPrefix) && metaEntry && typeof metaEntry === "object") {
|
|
2043
|
+
const relPath = metaKey.slice(oldPrefix.length);
|
|
2044
|
+
const localPath = path6.join(absolutePath, relPath);
|
|
2045
|
+
try {
|
|
2046
|
+
await fs6.access(localPath);
|
|
2047
|
+
} catch {
|
|
2048
|
+
cloudOnlyFiles.push({
|
|
2049
|
+
oldKey: metaKey,
|
|
2050
|
+
newKey: newPrefix + relPath,
|
|
2051
|
+
entry: metaEntry
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
for (const localFile of localFiles) {
|
|
2057
|
+
const fileOldPath = path6.join(absolutePath, localFile.relativePath);
|
|
2058
|
+
const fileNewPath = path6.join(newAbsolutePath, localFile.relativePath);
|
|
2059
|
+
const fileOldKey = oldPrefix + localFile.relativePath;
|
|
2060
|
+
const fileNewKey = newPrefix + localFile.relativePath;
|
|
2061
|
+
const fileEntry = meta[fileOldKey];
|
|
2062
|
+
sourceFolders.add(path6.dirname(fileOldPath));
|
|
2063
|
+
await fs6.mkdir(path6.dirname(fileNewPath), { recursive: true });
|
|
2064
|
+
await fs6.rename(fileOldPath, fileNewPath);
|
|
2065
|
+
if (localFile.isImage && fileEntry) {
|
|
2066
|
+
const oldThumbPaths = getAllThumbnailPaths(fileOldKey);
|
|
2067
|
+
const newThumbPaths = getAllThumbnailPaths(fileNewKey);
|
|
2068
|
+
for (let t = 0; t < oldThumbPaths.length; t++) {
|
|
2069
|
+
const oldThumbPath = getPublicPath(oldThumbPaths[t]);
|
|
2070
|
+
const newThumbPath = getPublicPath(newThumbPaths[t]);
|
|
2071
|
+
try {
|
|
2072
|
+
await fs6.access(oldThumbPath);
|
|
2073
|
+
sourceFolders.add(path6.dirname(oldThumbPath));
|
|
2074
|
+
await fs6.mkdir(path6.dirname(newThumbPath), { recursive: true });
|
|
2075
|
+
await fs6.rename(oldThumbPath, newThumbPath);
|
|
2076
|
+
} catch {
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
const fileIsInCloud = fileEntry.c !== void 0;
|
|
2080
|
+
const fileCdnUrl2 = fileIsInCloud ? cdnUrls[fileEntry.c] : void 0;
|
|
2081
|
+
const fileIsInR2 = fileIsInCloud && fileCdnUrl2 === r2PublicUrl;
|
|
2082
|
+
const fileHasThumbs = isProcessed(fileEntry);
|
|
2083
|
+
if (fileIsInR2) {
|
|
2084
|
+
await deleteFromCdn(fileOldKey, fileHasThumbs);
|
|
2085
|
+
await uploadOriginalToCdn(fileNewKey);
|
|
2086
|
+
if (fileHasThumbs) {
|
|
2087
|
+
await uploadToCdn(fileNewKey);
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
delete meta[fileOldKey];
|
|
2091
|
+
meta[fileNewKey] = fileEntry;
|
|
2092
|
+
}
|
|
2093
|
+
processedFiles++;
|
|
2094
|
+
sendEvent({
|
|
2095
|
+
type: "progress",
|
|
2096
|
+
current: processedFiles,
|
|
2097
|
+
total: totalFiles,
|
|
2098
|
+
moved: moved.length,
|
|
2099
|
+
percent: Math.round(processedFiles / totalFiles * 100),
|
|
2100
|
+
currentFile: path6.basename(localFile.relativePath)
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
for (const cloudFile of cloudOnlyFiles) {
|
|
2104
|
+
const cloudEntry = cloudFile.entry;
|
|
2105
|
+
const cloudIsInCloud = cloudEntry.c !== void 0;
|
|
2106
|
+
const cloudCdnUrl = cloudIsInCloud ? cdnUrls[cloudEntry.c] : void 0;
|
|
2107
|
+
const cloudIsInR2 = cloudIsInCloud && cloudCdnUrl === r2PublicUrl;
|
|
2108
|
+
const cloudHasThumbs = isProcessed(cloudEntry);
|
|
2109
|
+
if (cloudIsInR2) {
|
|
2110
|
+
try {
|
|
2111
|
+
const cloudLocalPath = getPublicPath(cloudFile.newKey);
|
|
2112
|
+
const buffer = await downloadFromCdn(cloudFile.oldKey);
|
|
2113
|
+
await fs6.mkdir(path6.dirname(cloudLocalPath), { recursive: true });
|
|
2114
|
+
await fs6.writeFile(cloudLocalPath, buffer);
|
|
2115
|
+
if (cloudHasThumbs) {
|
|
2116
|
+
const oldThumbPaths = getAllThumbnailPaths(cloudFile.oldKey);
|
|
2117
|
+
const newThumbPaths = getAllThumbnailPaths(cloudFile.newKey);
|
|
2118
|
+
for (let t = 0; t < oldThumbPaths.length; t++) {
|
|
2119
|
+
try {
|
|
2120
|
+
const thumbBuffer = await downloadFromCdn(oldThumbPaths[t]);
|
|
2121
|
+
const newThumbLocalPath = getPublicPath(newThumbPaths[t]);
|
|
2122
|
+
await fs6.mkdir(path6.dirname(newThumbLocalPath), { recursive: true });
|
|
2123
|
+
await fs6.writeFile(newThumbLocalPath, thumbBuffer);
|
|
2124
|
+
} catch {
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
await deleteFromCdn(cloudFile.oldKey, cloudHasThumbs);
|
|
2129
|
+
await uploadOriginalToCdn(cloudFile.newKey);
|
|
2130
|
+
if (cloudHasThumbs) {
|
|
2131
|
+
await uploadToCdn(cloudFile.newKey);
|
|
2132
|
+
}
|
|
2133
|
+
try {
|
|
2134
|
+
await fs6.unlink(cloudLocalPath);
|
|
2135
|
+
} catch {
|
|
2136
|
+
}
|
|
2137
|
+
if (cloudHasThumbs) {
|
|
2138
|
+
await deleteLocalThumbnails(cloudFile.newKey);
|
|
2139
|
+
}
|
|
2140
|
+
await deleteEmptyFolders(path6.dirname(cloudLocalPath));
|
|
2141
|
+
} catch (err) {
|
|
2142
|
+
console.error(`Failed to move cloud file ${cloudFile.oldKey}:`, err);
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
delete meta[cloudFile.oldKey];
|
|
2146
|
+
meta[cloudFile.newKey] = cloudEntry;
|
|
2147
|
+
processedFiles++;
|
|
2148
|
+
sendEvent({
|
|
2149
|
+
type: "progress",
|
|
2150
|
+
current: processedFiles,
|
|
2151
|
+
total: totalFiles,
|
|
2152
|
+
moved: moved.length,
|
|
2153
|
+
percent: Math.round(processedFiles / totalFiles * 100),
|
|
2154
|
+
currentFile: path6.basename(cloudFile.newKey)
|
|
2155
|
+
});
|
|
2156
|
+
}
|
|
2157
|
+
sourceFolders.add(absolutePath);
|
|
2158
|
+
const oldThumbRelPath = oldKey.slice(1);
|
|
2159
|
+
const oldThumbFolder = path6.join(getPublicPath("images"), oldThumbRelPath);
|
|
2160
|
+
sourceFolders.add(oldThumbFolder);
|
|
2161
|
+
moved.push(itemPath);
|
|
2032
2162
|
}
|
|
2033
|
-
sendEvent({
|
|
2034
|
-
type: "progress",
|
|
2035
|
-
current: processedFiles,
|
|
2036
|
-
total: totalFiles,
|
|
2037
|
-
moved: moved.length,
|
|
2038
|
-
percent: Math.round(processedFiles / totalFiles * 100),
|
|
2039
|
-
currentFile: itemName
|
|
2040
|
-
});
|
|
2041
2163
|
}
|
|
2042
2164
|
} catch (err) {
|
|
2043
2165
|
console.error(`Failed to move ${itemName}:`, err);
|