import { http, clientIdHeaders } from './http.js'; export const vfs = { /** * GET /api/vfs * List files in the virtual filesystem for the selected company. * → 200 { files: [{ name, size, mime, updated_at, created_at, isText, isImage, isPdf }] } */ // #region GET /api/vfs — list list() { return http('/api/vfs'); }, // #endregion /** * GET /api/vfs/*path * Fetch raw content of a file (e.g. text for the editor). * @param {string} path */ // #region GET /api/vfs/*path — getText async getText(path) { const clean = String(path || '').replace(/^\/+/, ''); const res = await fetch(`/api/vfs/${clean}?raw=1`, { credentials: 'include', }); if (!res.ok) { throw new Error(`Datei konnte nicht geladen werden (${res.status} ${res.statusText})`); } return res.text(); }, // #endregion /** * PUT /api/vfs/*path * Create or update a file. * @param {string} path * @param {string} content * @param {string} [mime] */ // #region PUT /api/vfs/*path — save save(path, content, mime) { const clean = String(path || '').replace(/^\/+/, ''); return http(`/api/vfs/${clean}`, { method: 'PUT', body: { content, mime }, }); }, // #endregion /** * DELETE /api/vfs/*path * Delete a file. * @param {string} path */ // #region DELETE /api/vfs/*path — delete delete(path) { const clean = String(path || '').replace(/^\/+/, ''); return http(`/api/vfs/${clean}`, { method: 'DELETE', }); }, // #endregion /** * POST /api/vfs/upload * Upload multiple files or a single file to VFS. * @param {File[]|FileList|File} files * @param {string} [targetDir] */ // #region POST /api/vfs/upload — upload async upload(files, targetDir = '') { const formData = new FormData(); if (targetDir) formData.append('targetDir', targetDir); const list = Array.isArray(files) ? files : files instanceof FileList ? Array.from(files) : [files]; for (const f of list) { formData.append('files', f); } const res = await fetch('/api/vfs/upload', { method: 'POST', headers: { ...clientIdHeaders() }, credentials: 'include', body: formData, }); if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error(err.error || `Upload fehlgeschlagen (${res.status})`); } return res.json(); }, // #endregion /** * POST /api/vfs/mkdir * Create a directory in VFS. * @param {string} path */ // #region POST /api/vfs/mkdir — mkdir mkdir(path) { const clean = String(path || '').replace(/^\/+/, ''); return http('/api/vfs/mkdir', { method: 'POST', body: { path: clean }, }); }, // #endregion /** * POST /api/vfs/rename * Rename or move a file or directory in VFS. * @param {string} oldPath * @param {string} newPath */ // #region POST /api/vfs/rename — rename rename(oldPath, newPath) { const cleanOld = String(oldPath || '').replace(/^\/+/, ''); const cleanNew = String(newPath || '').replace(/^\/+/, ''); return http('/api/vfs/rename', { method: 'POST', body: { oldPath: cleanOld, newPath: cleanNew }, }); }, // #endregion /** * POST /api/vfs/*path — run a `.applet.js` file from VFS. * Path goes in the URL, run params in the JSON body. * @param {string} path VFS-relative applet path (e.g. `demo.applet.js`) * @param {{ input?: object, timeout?: number, max_output?: number }} [options] * → 200 { ok, result, columns, rows, warnings?, stdout, consoleLines, durationMs, truncated? } * `result` is a typed CSV string (`;`-separated, header row first), `columns` are the * declared `{ name, type }` pairs, `rows` is the data-row count. */ // #region POST /api/vfs/*path — runApplet runApplet(path, options = {}) { const clean = String(path || '').replace(/^\/+/, ''); const body = {}; if (options.input !== undefined) body.input = options.input; if (options.timeout !== undefined) body.timeout = options.timeout; if (options.max_output !== undefined) body.max_output = options.max_output; return http(`/api/vfs/${clean}`, { method: 'POST', body, }); }, // #endregion /** * POST /api/vfs/drafts/response * Send response to virtual draft request (action: read or list). * @param {{ requestId: string, content?: object|string, files?: Array, error?: string }} body */ // #region POST /api/vfs/drafts/response — respondDraft async respondDraft(body) { try { const res = await fetch('/api/vfs/drafts/response', { method: 'POST', headers: { 'Content-Type': 'application/json', ...clientIdHeaders(), }, credentials: 'include', body: JSON.stringify(body), }); if (!res.ok) { let errText = ''; try { const errData = await res.json(); errText = errData.error || errData.message; } catch { errText = await res.text().catch(() => ''); } console.error('[vfs] respondDraft failed:', res.status, errText); return { ok: false, error: errText }; } if (res.status === 204) return { ok: true }; const text = await res.text(); return text ? JSON.parse(text) : { ok: true }; } catch (err) { console.error('[vfs] respondDraft error:', err); return { ok: false, error: err.message }; } }, // #endregion };