/** * Files Routes - SharePoint file operations * * Note: Most file operations go through /api/jobs/:id/files * This route provides additional file utilities */ import { Hono } from 'hono'; import { graphService } from '../services/graphService'; import { tokenService } from '../services/tokenService'; import { pocketbaseService } from '../services/pocketbaseService'; import { authMiddleware, getUserId } from '../middleware/auth'; import { BadRequestError, NotFoundError } from '../middleware/errorHandler'; const files = new Hono(); // All file routes require authentication files.use('/*', authMiddleware); /** * GET /api/files * List files in a job's folder - requires jobId query param */ files.get('/', async (c) => { const userId = getUserId(c); const jobId = c.req.query('jobId'); if (!jobId) { throw new BadRequestError('jobId query parameter required'); } // Get job to find site/drive info const job = await pocketbaseService.getJob(jobId); if (!job) { throw new NotFoundError('Job not found'); } if (!job.site_id || !job.drive_id) { return c.json({ files: [] }); } const tokenResult = await tokenService.getToken(userId, 'graph'); if (!tokenResult) { throw new BadRequestError('Graph token not available'); } const result = await graphService.getFiles( tokenResult.token, job.site_id, job.drive_id, job.folder_path ); return c.json({ files: result.files }); }); /** * GET /api/files/download-url * Get download URL for a file - requires jobId and fileId */ files.get('/download-url', async (c) => { const userId = getUserId(c); const jobId = c.req.query('jobId'); const fileId = c.req.query('fileId'); if (!jobId || !fileId) { throw new BadRequestError('jobId and fileId query parameters required'); } // Get job to find site/drive info const job = await pocketbaseService.getJob(jobId); if (!job || !job.site_id || !job.drive_id) { throw new NotFoundError('Job not found or not configured for files'); } const tokenResult = await tokenService.getToken(userId, 'graph'); if (!tokenResult) { throw new BadRequestError('Graph token not available'); } const url = await graphService.getFileDownloadUrl( tokenResult.token, job.site_id, job.drive_id, fileId ); if (!url) { throw new NotFoundError('File not found'); } return c.json({ url }); }); /** * GET /api/files/search * Search files in a job's SharePoint site */ files.get('/search', async (c) => { const userId = getUserId(c); const jobId = c.req.query('jobId'); const query = c.req.query('q'); if (!jobId || !query) { throw new BadRequestError('jobId and q query parameters required'); } // Get job to find site info const job = await pocketbaseService.getJob(jobId); if (!job || !job.site_id) { throw new NotFoundError('Job not found or not configured for files'); } const tokenResult = await tokenService.getToken(userId, 'graph'); if (!tokenResult) { throw new BadRequestError('Graph token not available'); } const results = await graphService.searchFiles(tokenResult.token, job.site_id, query); return c.json({ files: results }); }); export default files;