fix: resolve API inconsistencies found by Mokoto

- Bug 1: No fix needed - frontend already uses PUT for document updates
- Bug 2: Changed folders API to use 'project' param (matches documents)
- Bug 3: GET /folders now works without project filter (lists all folders)

Changes:
- folders.js: Accept 'project' instead of 'projectId', make it optional
- folderService.js: Support listing all folders when projectId is null
- api.js: Updated getFolders() to use 'project' param consistently
This commit is contained in:
Hiro
2026-03-28 17:36:58 +00:00
parent 007c51a98f
commit 2d91e17c3e
3 changed files with 46 additions and 16 deletions

View File

@@ -11,15 +11,12 @@ import { NotFoundError, ValidationError } from '../utils/errors.js';
const router = Router();
router.use(authMiddleware);
// GET /folders?projectId=X&parentId=Y - List folders
// GET /folders?project=X&parentId=Y - List folders (project is optional, matches documents API)
router.get('/', async (req, res) => {
try {
const { projectId, parentId } = req.query;
if (!projectId) {
throw new ValidationError('projectId query parameter is required');
}
const { project, parentId } = req.query;
const folderService = getFolderService();
const folders = await folderService.getFolders(projectId, parentId || null);
const folders = await folderService.getFolders(project || null, parentId || null);
res.json({ folders });
} catch (err) {
if (err instanceof ValidationError) {

View File

@@ -157,13 +157,15 @@ export class FolderService {
}
}
async getFolders(projectId, parentId = null) {
// Verify project exists
const projectService = getProjectService(this.dataRoot);
await projectService.getProject(projectId);
async getFolders(projectId = null, parentId = null) {
const folders = [];
// If projectId is provided, verify it exists
if (projectId) {
const projectService = getProjectService(this.dataRoot);
await projectService.getProject(projectId);
}
if (parentId) {
// Get folders within a specific parent
const parentMeta = this._resolveFolderMeta(parentId, null, projectId);
@@ -187,8 +189,8 @@ export class FolderService {
folderCount: this._countSubFolders(join(entryPath, 'sub-folders')),
});
}
} else {
// Get root folders of the project
} else if (projectId) {
// Get root folders of a specific project
const rootFoldersPath = this._projectFoldersPath(projectId);
if (!pathExists(rootFoldersPath)) {
return folders;
@@ -208,6 +210,35 @@ export class FolderService {
folderCount: this._countSubFolders(join(entryPath, 'sub-folders')),
});
}
} else {
// No projectId provided - list folders from all projects
if (!pathExists(this.projectsPath)) {
return folders;
}
const projectEntries = listDir(this.projectsPath);
for (const projectEntry of projectEntries) {
const projectPath = join(this.projectsPath, projectEntry);
if (!isDirectory(projectPath)) continue;
const rootFoldersPath = join(projectPath, FOLDERS_DIR);
if (!pathExists(rootFoldersPath)) continue;
const entries = listDir(rootFoldersPath);
for (const entry of entries) {
const entryPath = join(rootFoldersPath, entry);
if (!isDirectory(entryPath)) continue;
const meta = readJSON(join(entryPath, FOLDER_META_FILE));
if (!meta) continue;
folders.push({
...meta,
documentCount: this._countDocuments(join(entryPath, 'documents')),
folderCount: this._countSubFolders(join(entryPath, 'sub-folders')),
});
}
}
}
return folders;