@gallop.software/studio 1.5.9 → 2.0.0
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/app/api/studio/[...path]/route.ts +1 -0
- package/app/layout.tsx +20 -0
- package/app/page.tsx +82 -0
- package/bin/studio.mjs +110 -0
- package/dist/handlers/index.js +84 -63
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/index.mjs +135 -114
- package/dist/handlers/index.mjs.map +1 -1
- package/dist/index.d.mts +14 -10
- package/dist/index.d.ts +14 -10
- package/dist/index.js +2 -177
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -179
- package/dist/index.mjs.map +1 -1
- package/next.config.mjs +22 -0
- package/package.json +18 -10
- package/src/components/AddNewModal.tsx +402 -0
- package/src/components/ErrorModal.tsx +89 -0
- package/src/components/R2SetupModal.tsx +400 -0
- package/src/components/StudioBreadcrumb.tsx +115 -0
- package/src/components/StudioButton.tsx +200 -0
- package/src/components/StudioContext.tsx +219 -0
- package/src/components/StudioDetailView.tsx +714 -0
- package/src/components/StudioFileGrid.tsx +704 -0
- package/src/components/StudioFileList.tsx +743 -0
- package/src/components/StudioFolderPicker.tsx +342 -0
- package/src/components/StudioModal.tsx +473 -0
- package/src/components/StudioPreview.tsx +399 -0
- package/src/components/StudioSettings.tsx +536 -0
- package/src/components/StudioToolbar.tsx +1448 -0
- package/src/components/StudioUI.tsx +731 -0
- package/src/components/styles/common.ts +236 -0
- package/src/components/tokens.ts +78 -0
- package/src/components/useStudioActions.tsx +497 -0
- package/src/config/index.ts +7 -0
- package/src/config/workspace.ts +52 -0
- package/src/handlers/favicon.ts +152 -0
- package/src/handlers/files.ts +784 -0
- package/src/handlers/images.ts +949 -0
- package/src/handlers/import.ts +190 -0
- package/src/handlers/index.ts +168 -0
- package/src/handlers/list.ts +627 -0
- package/src/handlers/scan.ts +311 -0
- package/src/handlers/utils/cdn.ts +234 -0
- package/src/handlers/utils/files.ts +64 -0
- package/src/handlers/utils/index.ts +4 -0
- package/src/handlers/utils/meta.ts +102 -0
- package/src/handlers/utils/thumbnails.ts +98 -0
- package/src/hooks/useFileList.ts +143 -0
- package/src/index.tsx +36 -0
- package/src/lib/api.ts +176 -0
- package/src/types.ts +119 -0
- package/dist/StudioUI-GJK45R3T.js +0 -6500
- package/dist/StudioUI-GJK45R3T.js.map +0 -1
- package/dist/StudioUI-QZ54STXE.mjs +0 -6500
- package/dist/StudioUI-QZ54STXE.mjs.map +0 -1
- package/dist/chunk-N6JYTJCB.js +0 -68
- package/dist/chunk-N6JYTJCB.js.map +0 -1
- package/dist/chunk-RHI3UROE.mjs +0 -68
- package/dist/chunk-RHI3UROE.mjs.map +0 -1
package/dist/handlers/index.js
CHANGED
|
@@ -15,8 +15,31 @@ var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
|
15
15
|
// src/handlers/utils/meta.ts
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
// src/config/workspace.ts
|
|
19
|
+
|
|
20
|
+
var workspacePath = null;
|
|
21
|
+
function getWorkspace() {
|
|
22
|
+
if (workspacePath === null) {
|
|
23
|
+
workspacePath = process.env.STUDIO_WORKSPACE || process.cwd();
|
|
24
|
+
}
|
|
25
|
+
return workspacePath;
|
|
26
|
+
}
|
|
27
|
+
function getPublicPath(...segments) {
|
|
28
|
+
return _path2.default.join(getWorkspace(), "public", ...segments);
|
|
29
|
+
}
|
|
30
|
+
function getDataPath(...segments) {
|
|
31
|
+
return _path2.default.join(getWorkspace(), "_data", ...segments);
|
|
32
|
+
}
|
|
33
|
+
function getSrcAppPath(...segments) {
|
|
34
|
+
return _path2.default.join(getWorkspace(), "src", "app", ...segments);
|
|
35
|
+
}
|
|
36
|
+
function getWorkspacePath(...segments) {
|
|
37
|
+
return _path2.default.join(getWorkspace(), ...segments);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/handlers/utils/meta.ts
|
|
18
41
|
async function loadMeta() {
|
|
19
|
-
const metaPath =
|
|
42
|
+
const metaPath = getDataPath("_studio.json");
|
|
20
43
|
try {
|
|
21
44
|
const content = await _fs.promises.readFile(metaPath, "utf-8");
|
|
22
45
|
return JSON.parse(content);
|
|
@@ -25,9 +48,9 @@ async function loadMeta() {
|
|
|
25
48
|
}
|
|
26
49
|
}
|
|
27
50
|
async function saveMeta(meta) {
|
|
28
|
-
const dataDir =
|
|
51
|
+
const dataDir = getDataPath();
|
|
29
52
|
await _fs.promises.mkdir(dataDir, { recursive: true });
|
|
30
|
-
const metaPath =
|
|
53
|
+
const metaPath = getDataPath("_studio.json");
|
|
31
54
|
const ordered = {};
|
|
32
55
|
if (meta._cdns) {
|
|
33
56
|
ordered._cdns = meta._cdns;
|
|
@@ -123,7 +146,7 @@ async function processImage(buffer, imageKey) {
|
|
|
123
146
|
const baseName = _path2.default.basename(keyWithoutSlash, _path2.default.extname(keyWithoutSlash));
|
|
124
147
|
const ext = _path2.default.extname(keyWithoutSlash).toLowerCase();
|
|
125
148
|
const imageDir = _path2.default.dirname(keyWithoutSlash);
|
|
126
|
-
const imagesPath =
|
|
149
|
+
const imagesPath = getPublicPath("images", imageDir === "." ? "" : imageDir);
|
|
127
150
|
await _fs.promises.mkdir(imagesPath, { recursive: true });
|
|
128
151
|
const isPng = ext === ".png";
|
|
129
152
|
const outputExt = isPng ? ".png" : ".jpg";
|
|
@@ -131,7 +154,7 @@ async function processImage(buffer, imageKey) {
|
|
|
131
154
|
o: { w: originalWidth, h: originalHeight }
|
|
132
155
|
};
|
|
133
156
|
const fullFileName = imageDir === "." ? `${baseName}${outputExt}` : `${imageDir}/${baseName}${outputExt}`;
|
|
134
|
-
const fullPath =
|
|
157
|
+
const fullPath = getPublicPath("images", fullFileName);
|
|
135
158
|
let fullWidth = originalWidth;
|
|
136
159
|
let fullHeight = originalHeight;
|
|
137
160
|
if (originalWidth > FULL_MAX_WIDTH) {
|
|
@@ -158,7 +181,7 @@ async function processImage(buffer, imageKey) {
|
|
|
158
181
|
const newHeight = Math.round(maxWidth * ratio);
|
|
159
182
|
const sizeFileName = `${baseName}${suffix}${outputExt}`;
|
|
160
183
|
const sizeFilePath = imageDir === "." ? sizeFileName : `${imageDir}/${sizeFileName}`;
|
|
161
|
-
const sizePath =
|
|
184
|
+
const sizePath = getPublicPath("images", sizeFilePath);
|
|
162
185
|
if (isPng) {
|
|
163
186
|
await _sharp2.default.call(void 0, buffer).resize(maxWidth, newHeight).png({ quality: 80 }).toFile(sizePath);
|
|
164
187
|
} else {
|
|
@@ -173,7 +196,6 @@ async function processImage(buffer, imageKey) {
|
|
|
173
196
|
|
|
174
197
|
// src/handlers/utils/cdn.ts
|
|
175
198
|
|
|
176
|
-
|
|
177
199
|
var _clients3 = require('@aws-sdk/client-s3');
|
|
178
200
|
async function purgeCloudflareCache(urls) {
|
|
179
201
|
const zoneId = process.env.CLOUDFLARE_ZONE_ID;
|
|
@@ -247,7 +269,7 @@ async function uploadToCdn(imageKey) {
|
|
|
247
269
|
if (!bucketName) throw new Error("R2 bucket not configured");
|
|
248
270
|
const r2 = getR2Client();
|
|
249
271
|
for (const thumbPath of _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
250
|
-
const localPath =
|
|
272
|
+
const localPath = getPublicPath(thumbPath);
|
|
251
273
|
try {
|
|
252
274
|
const fileBuffer = await _fs.promises.readFile(localPath);
|
|
253
275
|
await r2.send(
|
|
@@ -264,7 +286,7 @@ async function uploadToCdn(imageKey) {
|
|
|
264
286
|
}
|
|
265
287
|
async function deleteLocalThumbnails(imageKey) {
|
|
266
288
|
for (const thumbPath of _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
267
|
-
const localPath =
|
|
289
|
+
const localPath = getPublicPath(thumbPath);
|
|
268
290
|
try {
|
|
269
291
|
await _fs.promises.unlink(localPath);
|
|
270
292
|
} catch (e3) {
|
|
@@ -295,7 +317,7 @@ async function uploadOriginalToCdn(imageKey) {
|
|
|
295
317
|
const bucketName = process.env.CLOUDFLARE_R2_BUCKET_NAME;
|
|
296
318
|
if (!bucketName) throw new Error("R2 bucket not configured");
|
|
297
319
|
const r2 = getR2Client();
|
|
298
|
-
const localPath =
|
|
320
|
+
const localPath = getPublicPath(imageKey);
|
|
299
321
|
const fileBuffer = await _fs.promises.readFile(localPath);
|
|
300
322
|
await r2.send(
|
|
301
323
|
new (0, _clients3.PutObjectCommand)({
|
|
@@ -495,7 +517,7 @@ async function handleList(request) {
|
|
|
495
517
|
}
|
|
496
518
|
return _server.NextResponse.json({ items });
|
|
497
519
|
}
|
|
498
|
-
const absoluteDir =
|
|
520
|
+
const absoluteDir = getWorkspacePath(requestedPath);
|
|
499
521
|
try {
|
|
500
522
|
const dirEntries = await _fs.promises.readdir(absoluteDir, { withFileTypes: true });
|
|
501
523
|
for (const entry of dirEntries) {
|
|
@@ -606,7 +628,7 @@ async function handleList(request) {
|
|
|
606
628
|
hasThumbnail = true;
|
|
607
629
|
}
|
|
608
630
|
} else {
|
|
609
|
-
const localThumbPath =
|
|
631
|
+
const localThumbPath = getPublicPath(thumbPath);
|
|
610
632
|
try {
|
|
611
633
|
await _fs.promises.access(localThumbPath);
|
|
612
634
|
thumbnail = thumbPath;
|
|
@@ -627,7 +649,7 @@ async function handleList(request) {
|
|
|
627
649
|
}
|
|
628
650
|
if (!isPushedToCloud) {
|
|
629
651
|
try {
|
|
630
|
-
const filePath =
|
|
652
|
+
const filePath = getPublicPath(key);
|
|
631
653
|
const stats = await _fs.promises.stat(filePath);
|
|
632
654
|
fileSize = stats.size;
|
|
633
655
|
} catch (e9) {
|
|
@@ -687,7 +709,7 @@ async function handleSearch(request) {
|
|
|
687
709
|
hasThumbnail = true;
|
|
688
710
|
}
|
|
689
711
|
} else {
|
|
690
|
-
const localThumbPath =
|
|
712
|
+
const localThumbPath = getPublicPath(thumbPath);
|
|
691
713
|
try {
|
|
692
714
|
await _fs.promises.access(localThumbPath);
|
|
693
715
|
thumbnail = thumbPath;
|
|
@@ -751,7 +773,7 @@ async function handleListFolders() {
|
|
|
751
773
|
} catch (e11) {
|
|
752
774
|
}
|
|
753
775
|
}
|
|
754
|
-
const publicDir =
|
|
776
|
+
const publicDir = getPublicPath();
|
|
755
777
|
await scanDir(publicDir, "");
|
|
756
778
|
const folders = [];
|
|
757
779
|
folders.push({ path: "public", name: "public", depth: 0 });
|
|
@@ -801,28 +823,27 @@ async function handleFolderImages(request) {
|
|
|
801
823
|
const folders = foldersParam.split(",");
|
|
802
824
|
const meta = await loadMeta();
|
|
803
825
|
const fileEntries = getFileEntries(meta);
|
|
804
|
-
const
|
|
826
|
+
const allFiles = [];
|
|
805
827
|
const prefixes = folders.map((f) => {
|
|
806
828
|
const rel = f.replace(/^public\/?/, "");
|
|
807
829
|
return rel ? `/${rel}/` : "/";
|
|
808
830
|
});
|
|
809
831
|
for (const [key] of fileEntries) {
|
|
810
|
-
const fileName = _path2.default.basename(key);
|
|
811
|
-
if (!isImageFile(fileName)) continue;
|
|
812
832
|
for (const prefix of prefixes) {
|
|
813
833
|
if (key.startsWith(prefix) || prefix === "/" && key.startsWith("/")) {
|
|
814
|
-
|
|
834
|
+
allFiles.push(key.slice(1));
|
|
815
835
|
break;
|
|
816
836
|
}
|
|
817
837
|
}
|
|
818
838
|
}
|
|
819
839
|
return _server.NextResponse.json({
|
|
820
|
-
count:
|
|
821
|
-
images:
|
|
840
|
+
count: allFiles.length,
|
|
841
|
+
images: allFiles
|
|
842
|
+
// Keep as 'images' for backwards compatibility
|
|
822
843
|
});
|
|
823
844
|
} catch (error) {
|
|
824
|
-
console.error("Failed to get folder
|
|
825
|
-
return _server.NextResponse.json({ error: "Failed to get folder
|
|
845
|
+
console.error("Failed to get folder files:", error);
|
|
846
|
+
return _server.NextResponse.json({ error: "Failed to get folder files" }, { status: 500 });
|
|
826
847
|
}
|
|
827
848
|
}
|
|
828
849
|
|
|
@@ -872,7 +893,7 @@ async function handleUpload(request) {
|
|
|
872
893
|
imageKey = newKey;
|
|
873
894
|
}
|
|
874
895
|
const actualFileName = _path2.default.basename(imageKey);
|
|
875
|
-
const uploadDir =
|
|
896
|
+
const uploadDir = getPublicPath(relativeDir);
|
|
876
897
|
await _fs.promises.mkdir(uploadDir, { recursive: true });
|
|
877
898
|
await _fs.promises.writeFile(_path2.default.join(uploadDir, actualFileName), buffer);
|
|
878
899
|
if (!isMedia) {
|
|
@@ -921,7 +942,7 @@ async function handleDelete(request) {
|
|
|
921
942
|
errors.push(`Invalid path: ${itemPath}`);
|
|
922
943
|
continue;
|
|
923
944
|
}
|
|
924
|
-
const absolutePath =
|
|
945
|
+
const absolutePath = getWorkspacePath(itemPath);
|
|
925
946
|
const imageKey = "/" + itemPath.replace(/^public\//, "");
|
|
926
947
|
const entry = meta[imageKey];
|
|
927
948
|
const isPushedToCloud = _optionalChain([entry, 'optionalAccess', _18 => _18.c]) !== void 0;
|
|
@@ -935,7 +956,7 @@ async function handleDelete(request) {
|
|
|
935
956
|
const keyEntry = meta[key];
|
|
936
957
|
if (keyEntry && keyEntry.c === void 0) {
|
|
937
958
|
for (const thumbPath of _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, key)) {
|
|
938
|
-
const absoluteThumbPath =
|
|
959
|
+
const absoluteThumbPath = getPublicPath(thumbPath);
|
|
939
960
|
try {
|
|
940
961
|
await _fs.promises.unlink(absoluteThumbPath);
|
|
941
962
|
} catch (e13) {
|
|
@@ -951,7 +972,7 @@ async function handleDelete(request) {
|
|
|
951
972
|
if (!isInImagesFolder && entry) {
|
|
952
973
|
if (!isPushedToCloud) {
|
|
953
974
|
for (const thumbPath of _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
954
|
-
const absoluteThumbPath =
|
|
975
|
+
const absoluteThumbPath = getPublicPath(thumbPath);
|
|
955
976
|
try {
|
|
956
977
|
await _fs.promises.unlink(absoluteThumbPath);
|
|
957
978
|
} catch (e14) {
|
|
@@ -1007,8 +1028,8 @@ async function handleCreateFolder(request) {
|
|
|
1007
1028
|
return _server.NextResponse.json({ error: "Invalid folder name" }, { status: 400 });
|
|
1008
1029
|
}
|
|
1009
1030
|
const safePath = (parentPath || "public").replace(/\.\./g, "");
|
|
1010
|
-
const folderPath =
|
|
1011
|
-
if (!folderPath.startsWith(
|
|
1031
|
+
const folderPath = getWorkspacePath(safePath, sanitizedName);
|
|
1032
|
+
if (!folderPath.startsWith(getPublicPath())) {
|
|
1012
1033
|
return _server.NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
1013
1034
|
}
|
|
1014
1035
|
try {
|
|
@@ -1034,10 +1055,10 @@ async function handleRename(request) {
|
|
|
1034
1055
|
return _server.NextResponse.json({ error: "Invalid name" }, { status: 400 });
|
|
1035
1056
|
}
|
|
1036
1057
|
const safePath = oldPath.replace(/\.\./g, "");
|
|
1037
|
-
const absoluteOldPath =
|
|
1058
|
+
const absoluteOldPath = getWorkspacePath(safePath);
|
|
1038
1059
|
const parentDir = _path2.default.dirname(absoluteOldPath);
|
|
1039
1060
|
const absoluteNewPath = _path2.default.join(parentDir, sanitizedName);
|
|
1040
|
-
if (!absoluteOldPath.startsWith(
|
|
1061
|
+
if (!absoluteOldPath.startsWith(getPublicPath())) {
|
|
1041
1062
|
return _server.NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
1042
1063
|
}
|
|
1043
1064
|
try {
|
|
@@ -1065,8 +1086,8 @@ async function handleRename(request) {
|
|
|
1065
1086
|
const oldThumbPaths = _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, oldKey);
|
|
1066
1087
|
const newThumbPaths = _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, newKey);
|
|
1067
1088
|
for (let i = 0; i < oldThumbPaths.length; i++) {
|
|
1068
|
-
const oldThumbPath =
|
|
1069
|
-
const newThumbPath =
|
|
1089
|
+
const oldThumbPath = getPublicPath(oldThumbPaths[i]);
|
|
1090
|
+
const newThumbPath = getPublicPath(newThumbPaths[i]);
|
|
1070
1091
|
await _fs.promises.mkdir(_path2.default.dirname(newThumbPath), { recursive: true });
|
|
1071
1092
|
try {
|
|
1072
1093
|
await _fs.promises.rename(oldThumbPath, newThumbPath);
|
|
@@ -1107,8 +1128,8 @@ async function handleMoveStream(request) {
|
|
|
1107
1128
|
return;
|
|
1108
1129
|
}
|
|
1109
1130
|
const safeDestination = destination.replace(/\.\./g, "");
|
|
1110
|
-
const absoluteDestination =
|
|
1111
|
-
if (!absoluteDestination.startsWith(
|
|
1131
|
+
const absoluteDestination = getWorkspacePath(safeDestination);
|
|
1132
|
+
if (!absoluteDestination.startsWith(getPublicPath())) {
|
|
1112
1133
|
sendEvent({ type: "error", message: "Invalid destination" });
|
|
1113
1134
|
controller.close();
|
|
1114
1135
|
return;
|
|
@@ -1190,7 +1211,7 @@ async function handleMoveStream(request) {
|
|
|
1190
1211
|
meta[newKey] = newEntry;
|
|
1191
1212
|
moved.push(itemPath);
|
|
1192
1213
|
} else {
|
|
1193
|
-
const absolutePath =
|
|
1214
|
+
const absolutePath = getWorkspacePath(safePath);
|
|
1194
1215
|
if (absoluteDestination.startsWith(absolutePath + _path2.default.sep)) {
|
|
1195
1216
|
errors.push(`Cannot move ${itemName} into itself`);
|
|
1196
1217
|
continue;
|
|
@@ -1213,8 +1234,8 @@ async function handleMoveStream(request) {
|
|
|
1213
1234
|
const oldThumbPaths = _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, oldKey);
|
|
1214
1235
|
const newThumbPaths = _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, newKey);
|
|
1215
1236
|
for (let j = 0; j < oldThumbPaths.length; j++) {
|
|
1216
|
-
const oldThumbPath =
|
|
1217
|
-
const newThumbPath =
|
|
1237
|
+
const oldThumbPath = getPublicPath(oldThumbPaths[j]);
|
|
1238
|
+
const newThumbPath = getPublicPath(newThumbPaths[j]);
|
|
1218
1239
|
await _fs.promises.mkdir(_path2.default.dirname(newThumbPath), { recursive: true });
|
|
1219
1240
|
try {
|
|
1220
1241
|
await _fs.promises.rename(oldThumbPath, newThumbPath);
|
|
@@ -1320,7 +1341,7 @@ async function handleSync(request) {
|
|
|
1320
1341
|
const remoteUrl = `${existingCdnUrl}${imageKey}`;
|
|
1321
1342
|
originalBuffer = await downloadFromRemoteUrl(remoteUrl);
|
|
1322
1343
|
} else {
|
|
1323
|
-
const originalLocalPath =
|
|
1344
|
+
const originalLocalPath = getPublicPath(imageKey);
|
|
1324
1345
|
try {
|
|
1325
1346
|
originalBuffer = await _fs.promises.readFile(originalLocalPath);
|
|
1326
1347
|
} catch (e24) {
|
|
@@ -1339,7 +1360,7 @@ async function handleSync(request) {
|
|
|
1339
1360
|
urlsToPurge.push(`${publicUrl}${imageKey}`);
|
|
1340
1361
|
if (!isRemote && _chunkVI6QG6WTjs.isProcessed.call(void 0, entry)) {
|
|
1341
1362
|
for (const thumbPath of _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
1342
|
-
const localPath =
|
|
1363
|
+
const localPath = getPublicPath(thumbPath);
|
|
1343
1364
|
try {
|
|
1344
1365
|
const fileBuffer = await _fs.promises.readFile(localPath);
|
|
1345
1366
|
await r2.send(
|
|
@@ -1357,9 +1378,9 @@ async function handleSync(request) {
|
|
|
1357
1378
|
}
|
|
1358
1379
|
entry.c = cdnIndex;
|
|
1359
1380
|
if (!isRemote) {
|
|
1360
|
-
const originalLocalPath =
|
|
1381
|
+
const originalLocalPath = getPublicPath(imageKey);
|
|
1361
1382
|
for (const thumbPath of _chunkVI6QG6WTjs.getAllThumbnailPaths.call(void 0, imageKey)) {
|
|
1362
|
-
const localPath =
|
|
1383
|
+
const localPath = getPublicPath(thumbPath);
|
|
1363
1384
|
try {
|
|
1364
1385
|
await _fs.promises.unlink(localPath);
|
|
1365
1386
|
} catch (e26) {
|
|
@@ -1413,7 +1434,7 @@ async function handleReprocess(request) {
|
|
|
1413
1434
|
const existingCdnUrl = existingCdnIndex !== void 0 ? cdnUrls[existingCdnIndex] : void 0;
|
|
1414
1435
|
const isInOurR2 = existingCdnUrl === publicUrl;
|
|
1415
1436
|
const isRemote = existingCdnIndex !== void 0 && !isInOurR2;
|
|
1416
|
-
const originalPath =
|
|
1437
|
+
const originalPath = getPublicPath(imageKey);
|
|
1417
1438
|
try {
|
|
1418
1439
|
buffer = await _fs.promises.readFile(originalPath);
|
|
1419
1440
|
} catch (e28) {
|
|
@@ -1623,7 +1644,7 @@ async function handleReprocessStream(request) {
|
|
|
1623
1644
|
const existingCdnUrl = existingCdnIndex !== void 0 ? cdnUrls[existingCdnIndex] : void 0;
|
|
1624
1645
|
const isInOurR2 = existingCdnUrl === publicUrl;
|
|
1625
1646
|
const isRemote = existingCdnIndex !== void 0 && !isInOurR2;
|
|
1626
|
-
const originalPath =
|
|
1647
|
+
const originalPath = getPublicPath(imageKey);
|
|
1627
1648
|
try {
|
|
1628
1649
|
buffer = await _fs.promises.readFile(originalPath);
|
|
1629
1650
|
} catch (e32) {
|
|
@@ -1646,7 +1667,7 @@ async function handleReprocessStream(request) {
|
|
|
1646
1667
|
const isSvg = ext === ".svg";
|
|
1647
1668
|
if (isSvg) {
|
|
1648
1669
|
const imageDir = _path2.default.dirname(imageKey.slice(1));
|
|
1649
|
-
const imagesPath =
|
|
1670
|
+
const imagesPath = getPublicPath("images", imageDir === "." ? "" : imageDir);
|
|
1650
1671
|
await _fs.promises.mkdir(imagesPath, { recursive: true });
|
|
1651
1672
|
const fileName = _path2.default.basename(imageKey);
|
|
1652
1673
|
const destPath = _path2.default.join(imagesPath, fileName);
|
|
@@ -1746,7 +1767,7 @@ async function handleProcessAllStream() {
|
|
|
1746
1767
|
sendEvent({ type: "start", total });
|
|
1747
1768
|
for (let i = 0; i < imagesToProcess.length; i++) {
|
|
1748
1769
|
const { key, entry } = imagesToProcess[i];
|
|
1749
|
-
const fullPath =
|
|
1770
|
+
const fullPath = getPublicPath(key);
|
|
1750
1771
|
const existingCdnIndex = entry.c;
|
|
1751
1772
|
const existingCdnUrl = existingCdnIndex !== void 0 ? cdnUrls[existingCdnIndex] : void 0;
|
|
1752
1773
|
const isInOurR2 = existingCdnUrl === publicUrl;
|
|
@@ -1779,7 +1800,7 @@ async function handleProcessAllStream() {
|
|
|
1779
1800
|
const isSvg = ext === ".svg";
|
|
1780
1801
|
if (isSvg) {
|
|
1781
1802
|
const imageDir = _path2.default.dirname(key.slice(1));
|
|
1782
|
-
const imagesPath =
|
|
1803
|
+
const imagesPath = getPublicPath("images", imageDir === "." ? "" : imageDir);
|
|
1783
1804
|
await _fs.promises.mkdir(imagesPath, { recursive: true });
|
|
1784
1805
|
const fileName = _path2.default.basename(key);
|
|
1785
1806
|
const destPath = _path2.default.join(imagesPath, fileName);
|
|
@@ -1851,7 +1872,7 @@ async function handleProcessAllStream() {
|
|
|
1851
1872
|
} catch (e35) {
|
|
1852
1873
|
}
|
|
1853
1874
|
}
|
|
1854
|
-
const imagesDir =
|
|
1875
|
+
const imagesDir = getPublicPath("images");
|
|
1855
1876
|
try {
|
|
1856
1877
|
await findOrphans(imagesDir);
|
|
1857
1878
|
} catch (e36) {
|
|
@@ -1941,7 +1962,7 @@ async function handleDownloadStream(request) {
|
|
|
1941
1962
|
}
|
|
1942
1963
|
try {
|
|
1943
1964
|
const imageBuffer = await downloadFromCdn(imageKey);
|
|
1944
|
-
const localPath =
|
|
1965
|
+
const localPath = getPublicPath(imageKey.replace(/^\//, ""));
|
|
1945
1966
|
await _fs.promises.mkdir(_path2.default.dirname(localPath), { recursive: true });
|
|
1946
1967
|
await _fs.promises.writeFile(localPath, imageBuffer);
|
|
1947
1968
|
await deleteThumbnailsFromCdn(imageKey);
|
|
@@ -2045,7 +2066,7 @@ async function handleScanStream() {
|
|
|
2045
2066
|
} catch (e39) {
|
|
2046
2067
|
}
|
|
2047
2068
|
}
|
|
2048
|
-
const publicDir =
|
|
2069
|
+
const publicDir = getPublicPath();
|
|
2049
2070
|
await scanDir(publicDir);
|
|
2050
2071
|
const total = allFiles.length;
|
|
2051
2072
|
sendEvent({ type: "start", total });
|
|
@@ -2072,7 +2093,7 @@ async function handleScanStream() {
|
|
|
2072
2093
|
newKey = `/${baseName}-${counter}${ext}`;
|
|
2073
2094
|
}
|
|
2074
2095
|
const newRelativePath = `${baseName}-${counter}${ext}`;
|
|
2075
|
-
const newFullPath =
|
|
2096
|
+
const newFullPath = getPublicPath(newRelativePath);
|
|
2076
2097
|
try {
|
|
2077
2098
|
await _fs.promises.rename(fullPath, newFullPath);
|
|
2078
2099
|
renamed.push({ from: relativePath, to: newRelativePath });
|
|
@@ -2144,7 +2165,7 @@ async function handleScanStream() {
|
|
|
2144
2165
|
} catch (e41) {
|
|
2145
2166
|
}
|
|
2146
2167
|
}
|
|
2147
|
-
const imagesDir =
|
|
2168
|
+
const imagesDir = getPublicPath("images");
|
|
2148
2169
|
try {
|
|
2149
2170
|
await findOrphans(imagesDir);
|
|
2150
2171
|
} catch (e42) {
|
|
@@ -2188,7 +2209,7 @@ async function handleDeleteOrphans(request) {
|
|
|
2188
2209
|
errors.push(`Invalid path: ${orphanPath}`);
|
|
2189
2210
|
continue;
|
|
2190
2211
|
}
|
|
2191
|
-
const fullPath =
|
|
2212
|
+
const fullPath = getPublicPath(orphanPath);
|
|
2192
2213
|
try {
|
|
2193
2214
|
await _fs.promises.unlink(fullPath);
|
|
2194
2215
|
deleted.push(orphanPath);
|
|
@@ -2197,7 +2218,7 @@ async function handleDeleteOrphans(request) {
|
|
|
2197
2218
|
errors.push(orphanPath);
|
|
2198
2219
|
}
|
|
2199
2220
|
}
|
|
2200
|
-
const imagesDir =
|
|
2221
|
+
const imagesDir = getPublicPath("images");
|
|
2201
2222
|
async function removeEmptyDirs(dir) {
|
|
2202
2223
|
try {
|
|
2203
2224
|
const entries = await _fs.promises.readdir(dir, { withFileTypes: true });
|
|
@@ -2239,8 +2260,8 @@ async function handleDeleteOrphans(request) {
|
|
|
2239
2260
|
function parseImageUrl(url) {
|
|
2240
2261
|
const parsed = new URL(url);
|
|
2241
2262
|
const base = `${parsed.protocol}//${parsed.host}`;
|
|
2242
|
-
const
|
|
2243
|
-
return { base, path:
|
|
2263
|
+
const path9 = parsed.pathname;
|
|
2264
|
+
return { base, path: path9 };
|
|
2244
2265
|
}
|
|
2245
2266
|
async function processRemoteImage(url) {
|
|
2246
2267
|
const response = await fetch(url);
|
|
@@ -2289,20 +2310,20 @@ async function handleImportUrls(request) {
|
|
|
2289
2310
|
currentFile: url
|
|
2290
2311
|
});
|
|
2291
2312
|
try {
|
|
2292
|
-
const { base, path:
|
|
2293
|
-
const existingEntry = getMetaEntry(meta,
|
|
2313
|
+
const { base, path: path9 } = parseImageUrl(url);
|
|
2314
|
+
const existingEntry = getMetaEntry(meta, path9);
|
|
2294
2315
|
if (existingEntry) {
|
|
2295
|
-
skipped.push(
|
|
2316
|
+
skipped.push(path9);
|
|
2296
2317
|
continue;
|
|
2297
2318
|
}
|
|
2298
2319
|
const cdnIndex = getOrAddCdnIndex(meta, base);
|
|
2299
2320
|
const imageData = await processRemoteImage(url);
|
|
2300
|
-
setMetaEntry(meta,
|
|
2321
|
+
setMetaEntry(meta, path9, {
|
|
2301
2322
|
o: imageData.o,
|
|
2302
2323
|
b: imageData.b,
|
|
2303
2324
|
c: cdnIndex
|
|
2304
2325
|
});
|
|
2305
|
-
added.push(
|
|
2326
|
+
added.push(path9);
|
|
2306
2327
|
} catch (error) {
|
|
2307
2328
|
console.error(`Failed to import ${url}:`, error);
|
|
2308
2329
|
errors.push(url);
|
|
@@ -2385,7 +2406,7 @@ async function handleGenerateFavicon(request) {
|
|
|
2385
2406
|
error: "Source file must be named favicon.png or favicon.jpg"
|
|
2386
2407
|
}, { status: 400 });
|
|
2387
2408
|
}
|
|
2388
|
-
const sourcePath =
|
|
2409
|
+
const sourcePath = getPublicPath(imagePath.replace(/^\//, ""));
|
|
2389
2410
|
try {
|
|
2390
2411
|
await _promises2.default.access(sourcePath);
|
|
2391
2412
|
} catch (e46) {
|
|
@@ -2397,7 +2418,7 @@ async function handleGenerateFavicon(request) {
|
|
|
2397
2418
|
} catch (e47) {
|
|
2398
2419
|
return _server.NextResponse.json({ error: "Source file is not a valid image" }, { status: 400 });
|
|
2399
2420
|
}
|
|
2400
|
-
const outputDir =
|
|
2421
|
+
const outputDir = getSrcAppPath();
|
|
2401
2422
|
try {
|
|
2402
2423
|
await _promises2.default.access(outputDir);
|
|
2403
2424
|
} catch (e48) {
|