UNPKG

smc-hub

Version:

CoCalc: Backend webserver component

59 lines (53 loc) 1.58 kB
/* * 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>`; }