fs.ts
1,767 bytes
| 1 | import { mkdir, readdir } from 'node:fs/promises' |
|---|---|
| 2 | import { homedir } from 'node:os' |
| 3 | import path from 'node:path' |
| 4 | import type { FastifyInstance } from 'fastify' |
| 5 | import { FsMkdirRequestSchema, type FsBrowseResponse, type FsMkdirResponse } from '../../shared/types' |
| 6 | |
| 7 | export function registerFsRoutes(app: FastifyInstance): void { |
| 8 | app.get('/api/fs/browse', async (request, reply) => { |
| 9 | const query = request.query as { path?: string } |
| 10 | const target = query.path && query.path.trim().length > 0 ? query.path : homedir() |
| 11 | |
| 12 | let entries |
| 13 | try { |
| 14 | entries = await readdir(target, { withFileTypes: true }) |
| 15 | } catch (err) { |
| 16 | return reply.code(400).send({ error: err instanceof Error ? err.message : "can't read that folder" }) |
| 17 | } |
| 18 | |
| 19 | const directories = entries |
| 20 | .filter((entry) => entry.isDirectory() && !entry.name.startsWith('.')) |
| 21 | .map((entry) => ({ name: entry.name, path: path.join(target, entry.name) })) |
| 22 | .sort((a, b) => a.name.localeCompare(b.name)) |
| 23 | |
| 24 | const parentDir = path.dirname(target) |
| 25 | const parent = parentDir === target ? null : parentDir |
| 26 | |
| 27 | const response: FsBrowseResponse = { path: target, parent, directories } |
| 28 | return reply.send(response) |
| 29 | }) |
| 30 | |
| 31 | app.post('/api/fs/mkdir', async (request, reply) => { |
| 32 | const parsed = FsMkdirRequestSchema.safeParse(request.body) |
| 33 | if (!parsed.success) { |
| 34 | return reply.code(400).send({ error: parsed.error.message }) |
| 35 | } |
| 36 | |
| 37 | const newPath = path.join(parsed.data.path, parsed.data.name) |
| 38 | try { |
| 39 | await mkdir(newPath) |
| 40 | } catch (err) { |
| 41 | return reply.code(400).send({ error: err instanceof Error ? err.message : "can't create that folder" }) |
| 42 | } |
| 43 | |
| 44 | const response: FsMkdirResponse = { path: newPath } |
| 45 | return reply.send(response) |
| 46 | }) |
| 47 | } |
| 48 | |