@gallop.software/studio 0.1.113 → 0.1.115
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/{StudioUI-LGRI3HCE.mjs → StudioUI-73XFVFV4.mjs} +14 -16
- package/dist/StudioUI-73XFVFV4.mjs.map +1 -0
- package/dist/{StudioUI-HFZJ2YUQ.js → StudioUI-OVL65ONP.js} +14 -16
- package/dist/StudioUI-OVL65ONP.js.map +1 -0
- package/dist/handlers/index.js +151 -67
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/index.mjs +140 -56
- package/dist/handlers/index.mjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/StudioUI-HFZJ2YUQ.js.map +0 -1
- package/dist/StudioUI-LGRI3HCE.mjs.map +0 -1
package/dist/handlers/index.js
CHANGED
|
@@ -160,6 +160,31 @@ async function processImage(buffer, imageKey) {
|
|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
var _clients3 = require('@aws-sdk/client-s3');
|
|
163
|
+
async function purgeCloudflareCache(urls) {
|
|
164
|
+
const zoneId = process.env.CLOUDFLARE_ZONE_ID;
|
|
165
|
+
const apiToken = process.env.CLOUDFLARE_API_TOKEN;
|
|
166
|
+
if (!zoneId || !apiToken || urls.length === 0) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const response = await fetch(
|
|
171
|
+
`https://api.cloudflare.com/client/v4/zones/${zoneId}/purge_cache`,
|
|
172
|
+
{
|
|
173
|
+
method: "POST",
|
|
174
|
+
headers: {
|
|
175
|
+
"Authorization": `Bearer ${apiToken}`,
|
|
176
|
+
"Content-Type": "application/json"
|
|
177
|
+
},
|
|
178
|
+
body: JSON.stringify({ files: urls })
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
if (!response.ok) {
|
|
182
|
+
console.error("Cache purge failed:", await response.text());
|
|
183
|
+
}
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error("Cache purge error:", error);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
163
188
|
function getR2Client() {
|
|
164
189
|
const accountId = process.env.CLOUDFLARE_R2_ACCOUNT_ID;
|
|
165
190
|
const accessKeyId = process.env.CLOUDFLARE_R2_ACCESS_KEY_ID;
|
|
@@ -1022,7 +1047,7 @@ async function handleSync(request) {
|
|
|
1022
1047
|
const accessKeyId = process.env.CLOUDFLARE_R2_ACCESS_KEY_ID;
|
|
1023
1048
|
const secretAccessKey = process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY;
|
|
1024
1049
|
const bucketName = process.env.CLOUDFLARE_R2_BUCKET_NAME;
|
|
1025
|
-
const publicUrl = process.env.CLOUDFLARE_R2_PUBLIC_URL;
|
|
1050
|
+
const publicUrl = _optionalChain([process, 'access', _27 => _27.env, 'access', _28 => _28.CLOUDFLARE_R2_PUBLIC_URL, 'optionalAccess', _29 => _29.replace, 'call', _30 => _30(/\/\s*$/, "")]);
|
|
1026
1051
|
if (!accountId || !accessKeyId || !secretAccessKey || !bucketName || !publicUrl) {
|
|
1027
1052
|
return _server.NextResponse.json(
|
|
1028
1053
|
{ error: "R2 not configured. Set CLOUDFLARE_R2_* environment variables." },
|
|
@@ -1035,6 +1060,7 @@ async function handleSync(request) {
|
|
|
1035
1060
|
return _server.NextResponse.json({ error: "No image keys provided" }, { status: 400 });
|
|
1036
1061
|
}
|
|
1037
1062
|
const meta = await loadMeta();
|
|
1063
|
+
const cdnUrls = getCdnUrls(meta);
|
|
1038
1064
|
const cdnIndex = getOrAddCdnIndex(meta, publicUrl);
|
|
1039
1065
|
const r2 = new (0, _clients3.S3Client)({
|
|
1040
1066
|
region: "auto",
|
|
@@ -1043,63 +1069,80 @@ async function handleSync(request) {
|
|
|
1043
1069
|
});
|
|
1044
1070
|
const pushed = [];
|
|
1045
1071
|
const errors = [];
|
|
1072
|
+
const urlsToPurge = [];
|
|
1046
1073
|
for (const imageKey of imageKeys) {
|
|
1047
1074
|
const entry = getMetaEntry(meta, imageKey);
|
|
1048
1075
|
if (!entry) {
|
|
1049
1076
|
errors.push(`Image not found in meta: ${imageKey}. Run Scan first.`);
|
|
1050
1077
|
continue;
|
|
1051
1078
|
}
|
|
1052
|
-
|
|
1079
|
+
const existingCdnUrl = entry.c !== void 0 ? cdnUrls[entry.c] : void 0;
|
|
1080
|
+
const isAlreadyInOurR2 = existingCdnUrl === publicUrl;
|
|
1081
|
+
if (isAlreadyInOurR2) {
|
|
1053
1082
|
pushed.push(imageKey);
|
|
1054
1083
|
continue;
|
|
1055
1084
|
}
|
|
1056
|
-
|
|
1085
|
+
const isRemote = entry.c !== void 0 && existingCdnUrl !== publicUrl;
|
|
1086
|
+
if (!isRemote && !entry.p) {
|
|
1057
1087
|
errors.push(`Image not processed: ${imageKey}. Run Process Images first.`);
|
|
1058
1088
|
continue;
|
|
1059
1089
|
}
|
|
1060
1090
|
try {
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
const
|
|
1064
|
-
await
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
Key: imageKey.replace(/^\//, ""),
|
|
1068
|
-
Body: originalBuffer,
|
|
1069
|
-
ContentType: getContentType(imageKey)
|
|
1070
|
-
})
|
|
1071
|
-
);
|
|
1072
|
-
} catch (err) {
|
|
1073
|
-
errors.push(`Original file not found: ${imageKey}`);
|
|
1074
|
-
continue;
|
|
1075
|
-
}
|
|
1076
|
-
for (const thumbPath of _chunkLEOQKJCLjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
1077
|
-
const localPath = _path2.default.join(process.cwd(), "public", thumbPath);
|
|
1091
|
+
let originalBuffer;
|
|
1092
|
+
if (isRemote) {
|
|
1093
|
+
const remoteUrl = `${existingCdnUrl}${imageKey}`;
|
|
1094
|
+
originalBuffer = await downloadFromRemoteUrl(remoteUrl);
|
|
1095
|
+
} else {
|
|
1096
|
+
const originalLocalPath = _path2.default.join(process.cwd(), "public", imageKey);
|
|
1078
1097
|
try {
|
|
1079
|
-
|
|
1080
|
-
await r2.send(
|
|
1081
|
-
new (0, _clients3.PutObjectCommand)({
|
|
1082
|
-
Bucket: bucketName,
|
|
1083
|
-
Key: thumbPath.replace(/^\//, ""),
|
|
1084
|
-
Body: fileBuffer,
|
|
1085
|
-
ContentType: getContentType(thumbPath)
|
|
1086
|
-
})
|
|
1087
|
-
);
|
|
1098
|
+
originalBuffer = await _fs.promises.readFile(originalLocalPath);
|
|
1088
1099
|
} catch (e23) {
|
|
1100
|
+
errors.push(`Original file not found: ${imageKey}`);
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
await r2.send(
|
|
1105
|
+
new (0, _clients3.PutObjectCommand)({
|
|
1106
|
+
Bucket: bucketName,
|
|
1107
|
+
Key: imageKey.replace(/^\//, ""),
|
|
1108
|
+
Body: originalBuffer,
|
|
1109
|
+
ContentType: getContentType(imageKey)
|
|
1110
|
+
})
|
|
1111
|
+
);
|
|
1112
|
+
urlsToPurge.push(`${publicUrl}${imageKey}`);
|
|
1113
|
+
if (!isRemote && entry.p) {
|
|
1114
|
+
for (const thumbPath of _chunkLEOQKJCLjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
1115
|
+
const localPath = _path2.default.join(process.cwd(), "public", thumbPath);
|
|
1116
|
+
try {
|
|
1117
|
+
const fileBuffer = await _fs.promises.readFile(localPath);
|
|
1118
|
+
await r2.send(
|
|
1119
|
+
new (0, _clients3.PutObjectCommand)({
|
|
1120
|
+
Bucket: bucketName,
|
|
1121
|
+
Key: thumbPath.replace(/^\//, ""),
|
|
1122
|
+
Body: fileBuffer,
|
|
1123
|
+
ContentType: getContentType(thumbPath)
|
|
1124
|
+
})
|
|
1125
|
+
);
|
|
1126
|
+
urlsToPurge.push(`${publicUrl}${thumbPath}`);
|
|
1127
|
+
} catch (e24) {
|
|
1128
|
+
}
|
|
1089
1129
|
}
|
|
1090
1130
|
}
|
|
1091
1131
|
entry.c = cdnIndex;
|
|
1092
|
-
|
|
1093
|
-
const
|
|
1132
|
+
if (!isRemote) {
|
|
1133
|
+
const originalLocalPath = _path2.default.join(process.cwd(), "public", imageKey);
|
|
1134
|
+
for (const thumbPath of _chunkLEOQKJCLjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
1135
|
+
const localPath = _path2.default.join(process.cwd(), "public", thumbPath);
|
|
1136
|
+
try {
|
|
1137
|
+
await _fs.promises.unlink(localPath);
|
|
1138
|
+
} catch (e25) {
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1094
1141
|
try {
|
|
1095
|
-
await _fs.promises.unlink(
|
|
1096
|
-
} catch (
|
|
1142
|
+
await _fs.promises.unlink(originalLocalPath);
|
|
1143
|
+
} catch (e26) {
|
|
1097
1144
|
}
|
|
1098
1145
|
}
|
|
1099
|
-
try {
|
|
1100
|
-
await _fs.promises.unlink(originalLocalPath);
|
|
1101
|
-
} catch (e25) {
|
|
1102
|
-
}
|
|
1103
1146
|
pushed.push(imageKey);
|
|
1104
1147
|
} catch (error) {
|
|
1105
1148
|
console.error(`Failed to push ${imageKey}:`, error);
|
|
@@ -1107,53 +1150,71 @@ async function handleSync(request) {
|
|
|
1107
1150
|
}
|
|
1108
1151
|
}
|
|
1109
1152
|
await saveMeta(meta);
|
|
1153
|
+
if (urlsToPurge.length > 0) {
|
|
1154
|
+
await purgeCloudflareCache(urlsToPurge);
|
|
1155
|
+
}
|
|
1110
1156
|
return _server.NextResponse.json({
|
|
1111
1157
|
success: true,
|
|
1112
1158
|
pushed,
|
|
1113
1159
|
errors: errors.length > 0 ? errors : void 0
|
|
1114
1160
|
});
|
|
1115
1161
|
} catch (error) {
|
|
1116
|
-
console.error("Failed to
|
|
1117
|
-
return _server.NextResponse.json({ error: "Failed to
|
|
1162
|
+
console.error("Failed to push:", error);
|
|
1163
|
+
return _server.NextResponse.json({ error: "Failed to push to CDN" }, { status: 500 });
|
|
1118
1164
|
}
|
|
1119
1165
|
}
|
|
1120
1166
|
async function handleReprocess(request) {
|
|
1167
|
+
const publicUrl = _optionalChain([process, 'access', _31 => _31.env, 'access', _32 => _32.CLOUDFLARE_R2_PUBLIC_URL, 'optionalAccess', _33 => _33.replace, 'call', _34 => _34(/\/\s*$/, "")]);
|
|
1121
1168
|
try {
|
|
1122
1169
|
const { imageKeys } = await request.json();
|
|
1123
1170
|
if (!imageKeys || !Array.isArray(imageKeys) || imageKeys.length === 0) {
|
|
1124
1171
|
return _server.NextResponse.json({ error: "No image keys provided" }, { status: 400 });
|
|
1125
1172
|
}
|
|
1126
1173
|
const meta = await loadMeta();
|
|
1174
|
+
const cdnUrls = getCdnUrls(meta);
|
|
1127
1175
|
const processed = [];
|
|
1128
1176
|
const errors = [];
|
|
1177
|
+
const urlsToPurge = [];
|
|
1129
1178
|
for (const imageKey of imageKeys) {
|
|
1130
1179
|
try {
|
|
1131
1180
|
let buffer;
|
|
1132
1181
|
const entry = getMetaEntry(meta, imageKey);
|
|
1133
|
-
const
|
|
1134
|
-
const
|
|
1182
|
+
const existingCdnIndex = _optionalChain([entry, 'optionalAccess', _35 => _35.c]);
|
|
1183
|
+
const existingCdnUrl = existingCdnIndex !== void 0 ? cdnUrls[existingCdnIndex] : void 0;
|
|
1184
|
+
const isInOurR2 = existingCdnUrl === publicUrl;
|
|
1185
|
+
const isRemote = existingCdnIndex !== void 0 && !isInOurR2;
|
|
1135
1186
|
const originalPath = _path2.default.join(process.cwd(), "public", imageKey);
|
|
1136
1187
|
try {
|
|
1137
1188
|
buffer = await _fs.promises.readFile(originalPath);
|
|
1138
|
-
} catch (
|
|
1139
|
-
if (
|
|
1189
|
+
} catch (e27) {
|
|
1190
|
+
if (isInOurR2) {
|
|
1140
1191
|
buffer = await downloadFromCdn(imageKey);
|
|
1141
1192
|
const dir = _path2.default.dirname(originalPath);
|
|
1142
1193
|
await _fs.promises.mkdir(dir, { recursive: true });
|
|
1143
1194
|
await _fs.promises.writeFile(originalPath, buffer);
|
|
1195
|
+
} else if (isRemote && existingCdnUrl) {
|
|
1196
|
+
const remoteUrl = `${existingCdnUrl}${imageKey}`;
|
|
1197
|
+
buffer = await downloadFromRemoteUrl(remoteUrl);
|
|
1198
|
+
const dir = _path2.default.dirname(originalPath);
|
|
1199
|
+
await _fs.promises.mkdir(dir, { recursive: true });
|
|
1200
|
+
await _fs.promises.writeFile(originalPath, buffer);
|
|
1144
1201
|
} else {
|
|
1145
1202
|
throw new Error(`File not found: ${imageKey}`);
|
|
1146
1203
|
}
|
|
1147
1204
|
}
|
|
1148
1205
|
const updatedEntry = await processImage(buffer, imageKey);
|
|
1149
|
-
if (
|
|
1206
|
+
if (isInOurR2) {
|
|
1150
1207
|
updatedEntry.c = existingCdnIndex;
|
|
1151
1208
|
await uploadToCdn(imageKey);
|
|
1209
|
+
for (const thumbPath of _chunkLEOQKJCLjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
1210
|
+
urlsToPurge.push(`${publicUrl}${thumbPath}`);
|
|
1211
|
+
}
|
|
1152
1212
|
await deleteLocalThumbnails(imageKey);
|
|
1153
1213
|
try {
|
|
1154
1214
|
await _fs.promises.unlink(originalPath);
|
|
1155
|
-
} catch (
|
|
1215
|
+
} catch (e28) {
|
|
1156
1216
|
}
|
|
1217
|
+
} else if (isRemote) {
|
|
1157
1218
|
}
|
|
1158
1219
|
meta[imageKey] = updatedEntry;
|
|
1159
1220
|
processed.push(imageKey);
|
|
@@ -1163,6 +1224,9 @@ async function handleReprocess(request) {
|
|
|
1163
1224
|
}
|
|
1164
1225
|
}
|
|
1165
1226
|
await saveMeta(meta);
|
|
1227
|
+
if (urlsToPurge.length > 0) {
|
|
1228
|
+
await purgeCloudflareCache(urlsToPurge);
|
|
1229
|
+
}
|
|
1166
1230
|
return _server.NextResponse.json({
|
|
1167
1231
|
success: true,
|
|
1168
1232
|
processed,
|
|
@@ -1174,6 +1238,7 @@ async function handleReprocess(request) {
|
|
|
1174
1238
|
}
|
|
1175
1239
|
}
|
|
1176
1240
|
async function handleProcessAllStream() {
|
|
1241
|
+
const publicUrl = _optionalChain([process, 'access', _36 => _36.env, 'access', _37 => _37.CLOUDFLARE_R2_PUBLIC_URL, 'optionalAccess', _38 => _38.replace, 'call', _39 => _39(/\/\s*$/, "")]);
|
|
1177
1242
|
const encoder = new TextEncoder();
|
|
1178
1243
|
const stream = new ReadableStream({
|
|
1179
1244
|
async start(controller) {
|
|
@@ -1184,9 +1249,11 @@ async function handleProcessAllStream() {
|
|
|
1184
1249
|
};
|
|
1185
1250
|
try {
|
|
1186
1251
|
const meta = await loadMeta();
|
|
1252
|
+
const cdnUrls = getCdnUrls(meta);
|
|
1187
1253
|
const processed = [];
|
|
1188
1254
|
const errors = [];
|
|
1189
1255
|
const orphansRemoved = [];
|
|
1256
|
+
const urlsToPurge = [];
|
|
1190
1257
|
let alreadyProcessed = 0;
|
|
1191
1258
|
const imagesToProcess = [];
|
|
1192
1259
|
for (const [key, entry] of getFileEntries(meta)) {
|
|
@@ -1203,8 +1270,10 @@ async function handleProcessAllStream() {
|
|
|
1203
1270
|
for (let i = 0; i < imagesToProcess.length; i++) {
|
|
1204
1271
|
const { key, entry } = imagesToProcess[i];
|
|
1205
1272
|
const fullPath = _path2.default.join(process.cwd(), "public", key);
|
|
1206
|
-
const isInCloud = entry.c !== void 0;
|
|
1207
1273
|
const existingCdnIndex = entry.c;
|
|
1274
|
+
const existingCdnUrl = existingCdnIndex !== void 0 ? cdnUrls[existingCdnIndex] : void 0;
|
|
1275
|
+
const isInOurR2 = existingCdnUrl === publicUrl;
|
|
1276
|
+
const isRemote = existingCdnIndex !== void 0 && !isInOurR2;
|
|
1208
1277
|
sendEvent({
|
|
1209
1278
|
type: "progress",
|
|
1210
1279
|
current: i + 1,
|
|
@@ -1215,11 +1284,17 @@ async function handleProcessAllStream() {
|
|
|
1215
1284
|
});
|
|
1216
1285
|
try {
|
|
1217
1286
|
let buffer;
|
|
1218
|
-
if (
|
|
1287
|
+
if (isInOurR2) {
|
|
1219
1288
|
buffer = await downloadFromCdn(key);
|
|
1220
1289
|
const dir = _path2.default.dirname(fullPath);
|
|
1221
1290
|
await _fs.promises.mkdir(dir, { recursive: true });
|
|
1222
1291
|
await _fs.promises.writeFile(fullPath, buffer);
|
|
1292
|
+
} else if (isRemote && existingCdnUrl) {
|
|
1293
|
+
const remoteUrl = `${existingCdnUrl}${key}`;
|
|
1294
|
+
buffer = await downloadFromRemoteUrl(remoteUrl);
|
|
1295
|
+
const dir = _path2.default.dirname(fullPath);
|
|
1296
|
+
await _fs.promises.mkdir(dir, { recursive: true });
|
|
1297
|
+
await _fs.promises.writeFile(fullPath, buffer);
|
|
1223
1298
|
} else {
|
|
1224
1299
|
buffer = await _fs.promises.readFile(fullPath);
|
|
1225
1300
|
}
|
|
@@ -1239,20 +1314,26 @@ async function handleProcessAllStream() {
|
|
|
1239
1314
|
b: "",
|
|
1240
1315
|
p: 1
|
|
1241
1316
|
};
|
|
1317
|
+
if (isRemote) {
|
|
1318
|
+
delete meta[key].c;
|
|
1319
|
+
}
|
|
1242
1320
|
} else {
|
|
1243
1321
|
const processedEntry = await processImage(buffer, key);
|
|
1244
1322
|
meta[key] = {
|
|
1245
1323
|
...processedEntry,
|
|
1246
1324
|
p: 1,
|
|
1247
|
-
...
|
|
1325
|
+
...isInOurR2 ? { c: existingCdnIndex } : {}
|
|
1248
1326
|
};
|
|
1249
1327
|
}
|
|
1250
|
-
if (
|
|
1328
|
+
if (isInOurR2) {
|
|
1251
1329
|
await uploadToCdn(key);
|
|
1330
|
+
for (const thumbPath of _chunkLEOQKJCLjs.getAllThumbnailPaths.call(void 0, key)) {
|
|
1331
|
+
urlsToPurge.push(`${publicUrl}${thumbPath}`);
|
|
1332
|
+
}
|
|
1252
1333
|
await deleteLocalThumbnails(key);
|
|
1253
1334
|
try {
|
|
1254
1335
|
await _fs.promises.unlink(fullPath);
|
|
1255
|
-
} catch (
|
|
1336
|
+
} catch (e29) {
|
|
1256
1337
|
}
|
|
1257
1338
|
}
|
|
1258
1339
|
processed.push(key.slice(1));
|
|
@@ -1273,17 +1354,17 @@ async function handleProcessAllStream() {
|
|
|
1273
1354
|
async function findOrphans(dir, relativePath = "") {
|
|
1274
1355
|
try {
|
|
1275
1356
|
const entries = await _fs.promises.readdir(dir, { withFileTypes: true });
|
|
1276
|
-
for (const
|
|
1277
|
-
if (
|
|
1278
|
-
const
|
|
1279
|
-
const relPath = relativePath ? `${relativePath}/${
|
|
1280
|
-
if (
|
|
1281
|
-
await findOrphans(
|
|
1282
|
-
} else if (isImageFile(
|
|
1357
|
+
for (const fsEntry of entries) {
|
|
1358
|
+
if (fsEntry.name.startsWith(".")) continue;
|
|
1359
|
+
const entryFullPath = _path2.default.join(dir, fsEntry.name);
|
|
1360
|
+
const relPath = relativePath ? `${relativePath}/${fsEntry.name}` : fsEntry.name;
|
|
1361
|
+
if (fsEntry.isDirectory()) {
|
|
1362
|
+
await findOrphans(entryFullPath, relPath);
|
|
1363
|
+
} else if (isImageFile(fsEntry.name)) {
|
|
1283
1364
|
const publicPath = `/images/${relPath}`;
|
|
1284
1365
|
if (!trackedPaths.has(publicPath)) {
|
|
1285
1366
|
try {
|
|
1286
|
-
await _fs.promises.unlink(
|
|
1367
|
+
await _fs.promises.unlink(entryFullPath);
|
|
1287
1368
|
orphansRemoved.push(publicPath);
|
|
1288
1369
|
} catch (err) {
|
|
1289
1370
|
console.error(`Failed to remove orphan ${publicPath}:`, err);
|
|
@@ -1291,21 +1372,21 @@ async function handleProcessAllStream() {
|
|
|
1291
1372
|
}
|
|
1292
1373
|
}
|
|
1293
1374
|
}
|
|
1294
|
-
} catch (
|
|
1375
|
+
} catch (e30) {
|
|
1295
1376
|
}
|
|
1296
1377
|
}
|
|
1297
1378
|
const imagesDir = _path2.default.join(process.cwd(), "public", "images");
|
|
1298
1379
|
try {
|
|
1299
1380
|
await findOrphans(imagesDir);
|
|
1300
|
-
} catch (
|
|
1381
|
+
} catch (e31) {
|
|
1301
1382
|
}
|
|
1302
1383
|
async function removeEmptyDirs(dir) {
|
|
1303
1384
|
try {
|
|
1304
1385
|
const entries = await _fs.promises.readdir(dir, { withFileTypes: true });
|
|
1305
1386
|
let isEmpty = true;
|
|
1306
|
-
for (const
|
|
1307
|
-
if (
|
|
1308
|
-
const subDirEmpty = await removeEmptyDirs(_path2.default.join(dir,
|
|
1387
|
+
for (const fsEntry of entries) {
|
|
1388
|
+
if (fsEntry.isDirectory()) {
|
|
1389
|
+
const subDirEmpty = await removeEmptyDirs(_path2.default.join(dir, fsEntry.name));
|
|
1309
1390
|
if (!subDirEmpty) isEmpty = false;
|
|
1310
1391
|
} else {
|
|
1311
1392
|
isEmpty = false;
|
|
@@ -1315,15 +1396,18 @@ async function handleProcessAllStream() {
|
|
|
1315
1396
|
await _fs.promises.rmdir(dir);
|
|
1316
1397
|
}
|
|
1317
1398
|
return isEmpty;
|
|
1318
|
-
} catch (
|
|
1399
|
+
} catch (e32) {
|
|
1319
1400
|
return true;
|
|
1320
1401
|
}
|
|
1321
1402
|
}
|
|
1322
1403
|
try {
|
|
1323
1404
|
await removeEmptyDirs(imagesDir);
|
|
1324
|
-
} catch (
|
|
1405
|
+
} catch (e33) {
|
|
1325
1406
|
}
|
|
1326
1407
|
await saveMeta(meta);
|
|
1408
|
+
if (urlsToPurge.length > 0) {
|
|
1409
|
+
await purgeCloudflareCache(urlsToPurge);
|
|
1410
|
+
}
|
|
1327
1411
|
sendEvent({
|
|
1328
1412
|
type: "complete",
|
|
1329
1413
|
processed: processed.length,
|
|
@@ -1384,7 +1468,7 @@ async function handleScanStream() {
|
|
|
1384
1468
|
allFiles.push({ relativePath: relPath, fullPath });
|
|
1385
1469
|
}
|
|
1386
1470
|
}
|
|
1387
|
-
} catch (
|
|
1471
|
+
} catch (e34) {
|
|
1388
1472
|
}
|
|
1389
1473
|
}
|
|
1390
1474
|
const publicDir = _path2.default.join(process.cwd(), "public");
|
|
@@ -1444,7 +1528,7 @@ async function handleScanStream() {
|
|
|
1444
1528
|
h: metadata.height || 0,
|
|
1445
1529
|
b: blurhash
|
|
1446
1530
|
};
|
|
1447
|
-
} catch (
|
|
1531
|
+
} catch (e35) {
|
|
1448
1532
|
meta[imageKey] = { w: 0, h: 0 };
|
|
1449
1533
|
}
|
|
1450
1534
|
}
|