mirror of
https://github.com/nicotsx/zerobyte.git
synced 2025-12-10 12:10:51 +01:00
feat: local volume explore file system
This commit is contained in:
@@ -21,6 +21,8 @@ import {
|
||||
type ListContainersDto,
|
||||
type UpdateVolumeDto,
|
||||
type ListFilesDto,
|
||||
browseFilesystemDto,
|
||||
type BrowseFilesystemDto,
|
||||
} from "./volume.dto";
|
||||
import { volumeService } from "./volume.service";
|
||||
import { getVolumePath } from "./helpers";
|
||||
@@ -121,4 +123,15 @@ export const volumeController = new Hono()
|
||||
c.header("Cache-Control", "public, max-age=10, stale-while-revalidate=60");
|
||||
|
||||
return c.json<ListFilesDto>(response, 200);
|
||||
})
|
||||
.get("/filesystem/browse", browseFilesystemDto, async (c) => {
|
||||
const path = c.req.query("path") || "/";
|
||||
const result = await volumeService.browseFilesystem(path);
|
||||
|
||||
const response = {
|
||||
directories: result.directories,
|
||||
path: result.path,
|
||||
};
|
||||
|
||||
return c.json<BrowseFilesystemDto>(response, 200);
|
||||
});
|
||||
|
||||
@@ -335,3 +335,39 @@ export const listFilesDto = describeRoute({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Browse filesystem directories
|
||||
*/
|
||||
export const browseFilesystemResponse = type({
|
||||
directories: fileEntrySchema.array(),
|
||||
path: "string",
|
||||
});
|
||||
export type BrowseFilesystemDto = typeof browseFilesystemResponse.infer;
|
||||
|
||||
export const browseFilesystemDto = describeRoute({
|
||||
description: "Browse directories on the host filesystem",
|
||||
operationId: "browseFilesystem",
|
||||
tags: ["Volumes"],
|
||||
parameters: [
|
||||
{
|
||||
in: "query",
|
||||
name: "path",
|
||||
required: false,
|
||||
schema: {
|
||||
type: "string",
|
||||
},
|
||||
description: "Directory path to browse (absolute path, defaults to /)",
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
200: {
|
||||
description: "List of directories in the specified path",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: resolver(browseFilesystemResponse),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -276,7 +276,9 @@ const listFiles = async (name: string, subPath?: string) => {
|
||||
throw new InternalServerError("Volume is not mounted");
|
||||
}
|
||||
|
||||
const volumePath = getVolumePath(volume.name);
|
||||
// For directory volumes, use the configured path directly
|
||||
const volumePath =
|
||||
volume.config.backend === "directory" ? volume.config.path : getVolumePath(volume.name);
|
||||
|
||||
const requestedPath = subPath ? path.join(volumePath, subPath) : volumePath;
|
||||
|
||||
@@ -328,6 +330,48 @@ const listFiles = async (name: string, subPath?: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
const browseFilesystem = async (browsePath: string) => {
|
||||
const normalizedPath = path.normalize(browsePath);
|
||||
|
||||
try {
|
||||
const entries = await fs.readdir(normalizedPath, { withFileTypes: true });
|
||||
|
||||
const directories = await Promise.all(
|
||||
entries
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.map(async (entry) => {
|
||||
const fullPath = path.join(normalizedPath, entry.name);
|
||||
|
||||
try {
|
||||
const stats = await fs.stat(fullPath);
|
||||
return {
|
||||
name: entry.name,
|
||||
path: fullPath,
|
||||
type: "directory" as const,
|
||||
size: undefined,
|
||||
modifiedAt: stats.mtimeMs,
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
name: entry.name,
|
||||
path: fullPath,
|
||||
type: "directory" as const,
|
||||
size: undefined,
|
||||
modifiedAt: undefined,
|
||||
};
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
directories: directories.sort((a, b) => a.name.localeCompare(b.name)),
|
||||
path: normalizedPath,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new InternalServerError(`Failed to browse filesystem: ${toMessage(error)}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const volumeService = {
|
||||
listVolumes,
|
||||
createVolume,
|
||||
@@ -340,4 +384,5 @@ export const volumeService = {
|
||||
checkHealth,
|
||||
getContainersUsingVolume,
|
||||
listFiles,
|
||||
browseFilesystem,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user