Files
openmaic/OpenMAIC/app/api/coursewares/[id]/route.ts
T

50 lines
2.1 KiB
TypeScript

// Courseware detail — GET /api/coursewares/[id]
//
// Returns the latest published record for one courseware (or a specific
// version via `?version=N`). Public read path for the learner player.
import { type NextRequest } from 'next/server';
import { apiError, apiSuccess, API_ERROR_CODES } from '@/lib/server/api-response';
import { COURSEWARES_DIR, createFileCoursewareRepo } from '@/lib/courseware-repo/store';
import { toSummary } from '@/lib/courseware-repo';
import {
filterLearnerVisibleCoursewares,
isCoursewareLearnerVisible,
} from '@/lib/courseware-repo/learner-visibility';
import { createLogger } from '@/lib/logger';
const log = createLogger('Courseware Detail API');
export async function GET(request: NextRequest, context: { params: Promise<{ id: string }> }) {
try {
const { id } = await context.params;
if (!/^[a-zA-Z0-9_-]+$/.test(id)) {
return apiError(API_ERROR_CODES.INVALID_REQUEST, 400, 'Invalid courseware id');
}
const repo = createFileCoursewareRepo(COURSEWARES_DIR);
const versionParam = new URL(request.url).searchParams.get('version');
let record;
if (versionParam) {
const version = Number(versionParam);
if (!Number.isInteger(version) || version < 1) {
return apiError(API_ERROR_CODES.INVALID_REQUEST, 400, 'Invalid version');
}
record = await repo.getRecord(id, version);
if (record && !(await isCoursewareLearnerVisible(record))) record = null;
} else {
const candidates = (await repo.listRecords({ status: 'published' })).filter(
(candidate) => candidate.coursewareId === id,
);
const visible = await filterLearnerVisibleCoursewares(candidates);
record = visible.sort((a, b) => b.version - a.version)[0] ?? null;
}
if (!record || record.status !== 'published') {
return apiError(API_ERROR_CODES.INVALID_REQUEST, 404, 'Courseware not found');
}
return apiSuccess({ courseware: toSummary(record) });
} catch (error) {
log.error('Courseware detail failed:', error);
return apiError(API_ERROR_CODES.INTERNAL_ERROR, 500, 'Courseware detail failed');
}
}