diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index cfed653b..eff4e466 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -35,7 +35,21 @@ import { Language } from '../content/language.js'; * groups: * type: array * items: - * $ref: '#/components/schemas/Group' + * type: string + * description: ID of a group + * links: + * type: object + * properties: + * self: + * type: string + * description: Path to the assignment + * example: '/assignment/0' + * submissions: + * type: array + * items: + * type: string + * description: Path to the submissions for this assignment + * example: '/assignment/0/submissions' * required: * - within * - id diff --git a/backend/src/entities/classes/class-join-request.entity.ts b/backend/src/entities/classes/class-join-request.entity.ts index 0ae38cd1..228fc62c 100644 --- a/backend/src/entities/classes/class-join-request.entity.ts +++ b/backend/src/entities/classes/class-join-request.entity.ts @@ -2,6 +2,10 @@ import { Entity, Enum, ManyToOne } from '@mikro-orm/core'; import { Student } from '../users/student.entity.js'; import { Class } from './class.entity.js'; +/** + * @swagger + * tags: [Class] + */ @Entity() export class ClassJoinRequest { @ManyToOne({ diff --git a/backend/src/entities/classes/class.entity.ts b/backend/src/entities/classes/class.entity.ts index ecc11748..4dac4621 100644 --- a/backend/src/entities/classes/class.entity.ts +++ b/backend/src/entities/classes/class.entity.ts @@ -9,6 +9,35 @@ import { v4 } from 'uuid'; import { Teacher } from '../users/teacher.entity.js'; import { Student } from '../users/student.entity.js'; +/** + * @swagger + * tags: + * name: Class + * description: API for managing classes + * components: + * schemas: + * Class: + * type: object + * properties: + * classId: + * type: integer + * format: int8 + * displayName: + * type: string + * teachers: + * type: array + * items: + * type: string + * description: The id of a teacher + * students: + * type: array + * items: + * type: string + * description: The id of a student + * required: + * - teachers + * - students + */ @Entity() export class Class { @PrimaryKey() diff --git a/backend/src/entities/content/attachment.entity.ts b/backend/src/entities/content/attachment.entity.ts index 7a9dd946..462a5622 100644 --- a/backend/src/entities/content/attachment.entity.ts +++ b/backend/src/entities/content/attachment.entity.ts @@ -1,6 +1,28 @@ import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { LearningObject } from './learning-object.entity.js'; +/** + * @swagger + * components: + * schemas: + * Attachment: + * type: object + * properties: + * learningObject: + * $ref: '#/components/schemas/LearningObject' + * sequenceNumber: + * type: integer + * mimeType: + * type: string + * content: + * type: string + * format: binary + * required: + * - learningObject + * - sequenceNumber + * - mimeType + * - content + */ @Entity() export class Attachment { @ManyToOne({ diff --git a/backend/src/entities/content/language.ts b/backend/src/entities/content/language.ts index b5d18c80..622a035f 100644 --- a/backend/src/entities/content/language.ts +++ b/backend/src/entities/content/language.ts @@ -1,3 +1,23 @@ +/** + * @swagger + * components: + * schemas: + * Language: + * type: string + * enum: + * - nl + * - fr + * - en + * - de + * parameters: + * Language: + * in: query + * name: language + * description: Language of the content + * required: false + * schema: + * $ref: '#/components/schemas/Language' + */ export enum Language { Dutch = 'nl', French = 'fr', diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index bf499e8a..bce9ab30 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -12,6 +12,80 @@ import { Language } from './language.js'; import { Attachment } from './attachment.entity.js'; import { Teacher } from '../users/teacher.entity.js'; +/** + * @swagger + * tags: + * name: LearningObject + * description: API for managing learning objects + * components: + * schemas: + * LearningObject: + * type: object + * properties: + * hruid: + * type: string + * language: + * $ref: '#/components/schemas/Language' + * version: + * type: string + * default: '1' + * admins: + * type: array + * items: + * $ref: '#/components/schemas/Teacher' + * title: + * type: string + * description: + * type: string + * contentType: + * type: string + * keywords: + * type: array + * items: + * type: string + * targetAges: + * type: array + * items: + * type: integer + * nullable: true + * teacherExclusive: + * type: boolean + * default: false + * skosConcepts: + * type: array + * items: + * type: string + * educationalGoals: + * type: array + * items: + * $ref: '#/components/schemas/EducationalGoal' + * copyright: + * type: string + * default: '' + * license: + * type: string + * default: '' + * difficulty: + * type: integer + * nullable: true + * estimatedTime: + * type: integer + * returnValue: + * $ref: '#/components/schemas/ReturnValue' + * available: + * type: boolean + * default: true + * contentLocation: + * type: string + * nullable: true + * attachments: + * type: array + * items: + * $ref: '#/components/schemas/Attachment' + * content: + * type: string + * format: binary + */ @Entity() export class LearningObject { @PrimaryKey({ type: 'string' }) @@ -101,6 +175,18 @@ export class LearningObject { content!: Buffer; } +/** + * @swagger + * components: + * schemas: + * EducationalGoal: + * type: object + * properties: + * source: + * type: string + * id: + * type: string + */ @Embeddable() export class EducationalGoal { @Property({ type: 'string' }) @@ -110,6 +196,22 @@ export class EducationalGoal { id!: string; } +/** + * @swagger + * components: + * schemas: + * ReturnValue: + * type: object + * properties: + * callbackUrl: + * type: string + * format: uri + * callbackSchema: + * type: string + * required: + * - callbackUrl + * - callbackSchema + */ @Embeddable() export class ReturnValue { @Property({ type: 'string' }) diff --git a/backend/src/entities/content/learning-path.entity.ts b/backend/src/entities/content/learning-path.entity.ts index 28d3cadd..e4a6efb0 100644 --- a/backend/src/entities/content/learning-path.entity.ts +++ b/backend/src/entities/content/learning-path.entity.ts @@ -11,6 +11,46 @@ import { import { Language } from './language.js'; import { Teacher } from '../users/teacher.entity.js'; +/** + * @swagger + * tags: + * name: LearningPath + * description: API for managing learning paths + * components: + * schemas: + * LearningPath: + * type: object + * required: + * - hruid + * - language + * - admins + * - title + * - description + * - image + * properties: + * hruid: + * type: string + * description: Human readable identifier + * language: + * description: Language of the learning path + * schema: + * $ref: '#/components/schemas/Language' + * admins: + * type: array + * items: + * $ref: '#/components/schemas/Teacher' + * title: + * type: string + * description: + * type: string + * image: + * type: string + * nodes: + * type: array + * items: + * schema: + * $ref: '#/components/schemas/LearningPathNode' + */ @Entity() export class LearningPath { @PrimaryKey({ type: 'string' }) diff --git a/backend/src/entities/users/teacher.entity.ts b/backend/src/entities/users/teacher.entity.ts index 9f11a3b0..fa1731b7 100644 --- a/backend/src/entities/users/teacher.entity.ts +++ b/backend/src/entities/users/teacher.entity.ts @@ -2,6 +2,23 @@ import { Collection, Entity, ManyToMany } from '@mikro-orm/core'; import { User } from './user.entity.js'; import { Class } from '../classes/class.entity.js'; +/** + * @swagger + * tags: + * name: Teacher + * description: API for managing teachers + * components: + * schemas: + * Teacher: + * type: object + * required: + * - classes + * properties: + * classes: + * type: array + * items: + * $ref: '#/components/schemas/Class' + */ @Entity() export class Teacher extends User { @ManyToMany(() => { diff --git a/backend/src/routes/class.ts b/backend/src/routes/class.ts index 6f8f324e..6924184a 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/class.ts @@ -1,7 +1,40 @@ +/** + * @swagger + * components: + * parameters: + * id: + * in: path + * name: id + * schema: + * type: string + * description: The id of the class + * required: true + * example: 0 + */ + import express from 'express'; const router = express.Router(); -// Root endpoint used to search objects +/** + * @swagger + * /class: + * get: + * summary: Get a list of classes + * tags: [Class] + * responses: + * 200: + * description: A list of classes + * content: + * application/json: + * schema: + * type: object + * properties: + * classes: + * type: array + * items: + * type: string + * example: '0' + */ router.get('/', (req, res) => { res.json({ classes: ['0', '1'], @@ -9,6 +42,22 @@ router.get('/', (req, res) => { }); // Information about an class with id 'id' +/** + * @swagger + * /class/{id}: + * get: + * summary: Get a class by id + * tags: [Class] + * parameters: + * - $ref: '#/components/parameters/id' + * responses: + * 200: + * description: A class + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Class' + */ router.get('/:id', (req, res) => { res.json({ id: req.params.id, diff --git a/backend/src/routes/learningObjects.ts b/backend/src/routes/learningObjects.ts index 416602b5..a38bf6a6 100644 --- a/backend/src/routes/learningObjects.ts +++ b/backend/src/routes/learningObjects.ts @@ -1,3 +1,10 @@ +/** + * @swagger + * tags: + * name: LearningObject + * description: API for managing learning objects + */ + import express from 'express'; import { getAllLearningObjects, @@ -8,20 +15,67 @@ const router = express.Router(); // DWENGO learning objects -// Queries: hruid(path), full, language -// Route to fetch list of learning objects based on hruid of learning path - -// Route 1: list of object hruids -// Example 1: http://localhost:3000/learningObject?hruid=un_artificiele_intelligentie - -// Route 2: list of object data -// Example 2: http://localhost:3000/learningObject?full=true&hruid=un_artificiele_intelligentie +/** + * @swagger + * /learningObject: + * get: + * summary: Get a list of learning objects + * tags: [LearningObject] + * parameters: + * - in: query + * name: hruid + * schema: + * type: string + * description: + * The hruid of the learning path to get learning objects from + * example: un_artificiele_intelligentie + * - in: query + * name: full + * description: Whether to return full object data + * - $ref: '#/components/parameters/Language' + * responses: + * 200: + * description: A list of learning objects + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/LearningObject' + * 400: + * description: HRUID query is required + * 500: + * description: Internal server error + */ router.get('/', getAllLearningObjects); -// Parameter: hruid of learning object -// Query: language -// Route to fetch data of one learning object based on its hruid -// Example: http://localhost:3000/learningObject/un_ai7 +/** + * @swagger + * /learningObject/{hruid}: + * get: + * summary: Get a learning object by hruid + * tags: [LearningObject] + * parameters: + * - in: path + * name: hruid + * schema: + * type: string + * required: true + * description: The hruid of the learning object + * example: un_ai7 + * - $ref: '#/components/parameters/Language' + * responses: + * 200: + * description: A learning object + * content: + * application/json: + * schema: + * $ref: "#/components/schemas/LearningObject" + * 400: + * description: HRUID parameter is required + * 500: + * description: Internal server error + */ router.get('/:hruid', getLearningObject); export default router; diff --git a/backend/src/routes/question.ts b/backend/src/routes/question.ts index f683d998..563a8cea 100644 --- a/backend/src/routes/question.ts +++ b/backend/src/routes/question.ts @@ -2,6 +2,10 @@ import express from 'express'; const router = express.Router(); // Root endpoint used to search objects +/** + * @swagger + * /question + */ router.get('/', (req, res) => { res.json({ questions: ['0', '1'], diff --git a/backend/src/services/learningPaths.ts b/backend/src/services/learningPaths.ts index 52b168ee..7433f453 100644 --- a/backend/src/services/learningPaths.ts +++ b/backend/src/services/learningPaths.ts @@ -1,9 +1,11 @@ import { fetchWithLogging } from '../util/apiHelper.js'; import { DWENGO_API_BASE } from '../config.js'; import { - LearningPath, LearningPathResponse, } from '../interfaces/learningPath.js'; +import { + LearningPath +} from '../entities/content/learning-path.entity.js'; import { getLogger, Logger } from '../logging/initalize.js'; const logger: Logger = getLogger(); diff --git a/package-lock.json b/package-lock.json index 250898b9..d0f08893 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,7 +56,6 @@ "ts-node": "^10.9.2", "tsx": "^4.19.3", "typescript": "^5.7.3", - "typescript-json-schema": "^0.65.1", "vitest": "^3.0.6" } }, @@ -6355,13 +6354,6 @@ "version": "1.0.1", "license": "MIT" }, - "node_modules/path-equal": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", - "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==", - "dev": true, - "license": "MIT" - }, "node_modules/path-exists": { "version": "4.0.0", "dev": true, @@ -8296,103 +8288,6 @@ "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/typescript-json-schema": { - "version": "0.65.1", - "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.65.1.tgz", - "integrity": "sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@types/json-schema": "^7.0.9", - "@types/node": "^18.11.9", - "glob": "^7.1.7", - "path-equal": "^1.2.5", - "safe-stable-stringify": "^2.2.0", - "ts-node": "^10.9.1", - "typescript": "~5.5.0", - "yargs": "^17.1.1" - }, - "bin": { - "typescript-json-schema": "bin/typescript-json-schema" - } - }, - "node_modules/typescript-json-schema/node_modules/@types/node": { - "version": "18.19.79", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.79.tgz", - "integrity": "sha512-90K8Oayimbctc5zTPHPfZloc/lGVs7f3phUAAMcTgEPtg8kKquGZDERC8K4vkBYkQQh48msiYUslYtxTWvqcAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/typescript-json-schema/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/typescript-json-schema/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typescript-json-schema/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/typescript-json-schema/node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-json-schema/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, - "license": "MIT" - }, "node_modules/undici-types": { "version": "6.20.0", "license": "MIT"