UNPKG

cloudcmd

Version:

File manager for the web with console and editor

126 lines (99 loc) 2.98 kB
import {homedir} from 'node:os'; import {readFile as _readFile} from 'node:fs/promises'; import {join} from 'node:path'; // warm up worker cache import {montag} from 'montag'; import {tryToCatch} from 'try-to-catch'; import currify from 'currify'; import {putout, codeframe} from 'putout'; // warm up worker cache transpile(''); const PREFIX = '/api/v1/user-menu'; export const userMenu = currify(async ({menuName, readFile = _readFile, config}, req, res, next) => { if (!req.url.startsWith(PREFIX)) return next(); const {method} = req; if (method === 'GET') return await onGET({ req, res, menuName, readFile, config, }); next(); }); async function onGET({req, res, menuName, readFile, config}) { const {dir} = req.query; const url = req.url.replace(PREFIX, ''); if (url === '/default') return await sendDefaultMenu(res, { readFile, }); const {findUp} = await import('find-up'); const cwd = join(config('root'), dir); const [errorFind, currentMenuPath] = await tryToCatch(findUp, [menuName], { cwd, }); if (errorFind && errorFind.code !== 'ENOENT') return res .status(404) .send(errorFind.message); const homeMenuPath = join(homedir(), menuName); const menuPath = currentMenuPath || homeMenuPath; const [e, source] = await tryToCatch(readFile, menuPath, 'utf8'); if (e && e.code !== 'ENOENT') return res .status(404) .send(e.message); if (e) return await sendDefaultMenu(res, { readFile, }); const [parseError, result] = await transpile(source); if (parseError) return res .type('js') .send(getError(parseError, source)); res .type('js') .send(result.code); } function getError(error, source) { return montag` const e = Error(\`<pre>${codeframe({ error, source, highlightCode: false, })}</pre>\`); e.code = 'frame'; throw e; `; } async function sendDefaultMenu(res, {readFile}) { const menu = await getDefaultMenu({ readFile, }); res .type('js') .send(menu); } async function transpile(source) { return await tryToCatch(putout, source, { rules: { 'nodejs/convert-esm-to-commonjs': 'on', }, plugins: [ 'nodejs', 'cloudcmd', ], }); } async function getDefaultMenu({readFile}) { const DEFAULT_MENU_PATH = new URL('../static/user-menu.js', import.meta.url).pathname; const menu = await readFile(DEFAULT_MENU_PATH, 'utf8'); const [error, result] = await transpile(menu); if (error) return String(error); return result.code; }