smc-hub
Version:
CoCalc: Backend webserver component
59 lines (53 loc) • 1.58 kB
text/typescript
/*
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
*/
/*
Utilities that are useful for getting directory listings.
*/
import { lstat, readdir } from "fs";
import { callback, map } from "awaiting";
interface FileInfo {
name: string;
error?: Error;
isdir?: boolean;
size?: number;
mtime?: number;
}
export async function get_listing(dir: string): Promise<FileInfo[]> {
const files: string[] = await callback(readdir, dir);
async function get_metadata(file: string): Promise<FileInfo> {
const obj: FileInfo = { name: file };
// use lstat instead of stat so it works on symlinks too
try {
const stats = await callback(lstat, dir + "/" + file);
if (stats.isDirectory()) {
obj.isdir = true;
} else {
obj.size = stats.size;
}
obj.mtime = Math.floor(stats.mtime.valueOf() / 1000);
} catch (err) {
obj.error = err;
}
return obj;
}
return await map(files, 10, get_metadata);
}
export function render_directory_listing(
data: FileInfo[],
info: { project_id: string; path: string }
): string {
const s = ["<a href='..'>..</a>"];
for (const obj of data) {
let { name } = obj;
let link = encodeURIComponent(name);
if (obj.isdir) {
link += "/";
name += "/";
}
s.push(`<a style='text-decoration:none' href='${link}'>${name}</a>`);
}
const body = s.join("<br/>");
return `<body style='margin:40px'><h2>${info.project_id}:${info.path}</h2>${body}</body>`;
}