From f5b6a5a604f478fedb59acd71b269607836a8608 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 4 Mar 2025 12:31:12 +0100 Subject: [PATCH 01/49] feat: service en controller laag voor getStudent geimplementeerd --- backend/src/controllers/students.ts | 29 + backend/src/interfaces/students.ts | 12 + backend/src/routes/student.ts | 24 +- backend/src/services/students.ts | 18 + package-lock.json | 3293 ++++----------------------- 5 files changed, 459 insertions(+), 2917 deletions(-) create mode 100644 backend/src/controllers/students.ts create mode 100644 backend/src/interfaces/students.ts create mode 100644 backend/src/services/students.ts diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts new file mode 100644 index 00000000..b129eb57 --- /dev/null +++ b/backend/src/controllers/students.ts @@ -0,0 +1,29 @@ +import { Request, Response } from 'express'; +import { getStudentById } from "../services/students"; + +export async function getStudent( + req: Request, + res: Response, +): Promise { + try { + const username = req.params.id; + const student = await getStudentById(username); + + if (!student) { + res.status(404).json({ error: "Student not found" }); + return; + } else { + student.endpoints = { + classes: `/student/${req.params.id}/classes`, + questions: `/student/${req.params.id}/submissions`, + invitations: `/student/${req.params.id}/assignments`, + groups: `/student/${req.params.id}/groups`, + } + res.json(student); + } + + } catch (error) { + console.error('Error fetching learning objects:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} \ No newline at end of file diff --git a/backend/src/interfaces/students.ts b/backend/src/interfaces/students.ts new file mode 100644 index 00000000..cb13d3c2 --- /dev/null +++ b/backend/src/interfaces/students.ts @@ -0,0 +1,12 @@ +export interface StudentDTO { + id: string; + username: string; + firstName: string; + lastName: string; + endpoints?: { + classes: string; + questions: string; + invitations: string; + groups: string; + }; +} diff --git a/backend/src/routes/student.ts b/backend/src/routes/student.ts index a11c1fbc..6a6280e6 100644 --- a/backend/src/routes/student.ts +++ b/backend/src/routes/student.ts @@ -1,4 +1,6 @@ import express from 'express' +import { getStudentById } from '../services/students'; +import { getStudent } from '../controllers/students'; const router = express.Router(); // root endpoint used to search objects @@ -12,20 +14,7 @@ router.get('/', (req, res) => { }); // information about a student's profile -router.get('/:id', (req, res) => { - res.json({ - id: req.params.id, - firstName: 'Jimmy', - lastName: 'Faster', - username: 'JimmyFaster2', - endpoints: { - classes: `/student/${req.params.id}/classes`, - questions: `/student/${req.params.id}/submissions`, - invitations: `/student/${req.params.id}/assignments`, - groups: `/student/${req.params.id}/groups`, - }, - }); -}); +router.get('/:id', getStudent); // the list of classes a student is in router.get('/:id/classes', (req, res) => { @@ -56,4 +45,11 @@ router.get('/:id/groups', (req, res) => { }); }) +// a list of questions a user has created +router.get('/:id/questions', (req, res) => { + res.json({ + questions: [ '0' ], + }); +}) + export default router \ No newline at end of file diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts new file mode 100644 index 00000000..b2aa953b --- /dev/null +++ b/backend/src/services/students.ts @@ -0,0 +1,18 @@ +import { getStudentRepository } from "../data/repositories"; +import { StudentDTO } from "../interfaces/students"; + +export async function getStudentById(username: string): Promise { + const studentRepository = getStudentRepository(); + const student = await studentRepository.findByUsername(username); + + if (!student) return null; + else { + return { + id: student.username, + username: student.username, + firstName: student.firstName, + lastName: student.lastName, + } + } +} + diff --git a/package-lock.json b/package-lock.json index a7bf6bb9..88dcd6fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,15 +35,13 @@ "@mikro-orm/core": "^6.4.6", "@mikro-orm/postgresql": "^6.4.6", "@mikro-orm/reflection": "^6.4.6", + "@mikro-orm/sqlite": "6.4.6", "@types/js-yaml": "^4.0.9", "axios": "^1.8.1", - "@mikro-orm/sqlite": "6.4.6", - "dotenv": "^16.4.7", "express": "^5.0.1", - "uuid": "^11.1.0", "js-yaml": "^4.1.0", - "@types/js-yaml": "^4.0.9", + "uuid": "^11.1.0" }, "devDependencies": { "@mikro-orm/cli": "^6.4.6", @@ -56,27 +54,8 @@ "vitest": "^3.0.6" } }, - "backend/node_modules/@mikro-orm/sqlite": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/sqlite/-/sqlite-6.4.6.tgz", - "integrity": "sha512-BvoLd6qge2N4P2w9yjPP8+Ya5dxxnZrS6W3B2xm0m8BUesWnaCg2pmGXQpzFjrpYMg40mZ+RJWRTPq4M2Nl4lw==", - "dependencies": { - "@mikro-orm/knex": "6.4.6", - "fs-extra": "11.3.0", - "sqlite3": "5.1.7", - "sqlstring-sqlite": "0.1.1" - }, - "engines": { - "node": ">= 18.12.0" - }, - "peerDependencies": { - "@mikro-orm/core": "^6.0.0" - } - }, "backend/node_modules/globals": { "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", "engines": { @@ -119,8 +98,6 @@ }, "node_modules/@ampproject/remapping": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -133,8 +110,6 @@ }, "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -144,8 +119,6 @@ }, "node_modules/@antfu/utils": { "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", - "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", "dev": true, "license": "MIT", "funding": { @@ -154,8 +127,6 @@ }, "node_modules/@asamuzakjp/css-color": { "version": "2.8.3", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.3.tgz", - "integrity": "sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==", "dev": true, "license": "MIT", "dependencies": { @@ -168,8 +139,6 @@ }, "node_modules/@babel/code-frame": { "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { @@ -183,8 +152,6 @@ }, "node_modules/@babel/compat-data": { "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, "license": "MIT", "engines": { @@ -193,8 +160,6 @@ }, "node_modules/@babel/core": { "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", - "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", "dev": true, "license": "MIT", "dependencies": { @@ -224,8 +189,6 @@ }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -234,8 +197,6 @@ }, "node_modules/@babel/generator": { "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", - "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", "dev": true, "license": "MIT", "dependencies": { @@ -251,8 +212,6 @@ }, "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -262,8 +221,6 @@ }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { @@ -275,8 +232,6 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, "license": "MIT", "dependencies": { @@ -292,8 +247,6 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", "dependencies": { @@ -302,8 +255,6 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -312,8 +263,6 @@ }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz", - "integrity": "sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==", "dev": true, "license": "MIT", "dependencies": { @@ -334,8 +283,6 @@ }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -344,8 +291,6 @@ }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "dev": true, "license": "MIT", "dependencies": { @@ -358,8 +303,6 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { @@ -372,8 +315,6 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { @@ -390,8 +331,6 @@ }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -403,8 +342,6 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, "license": "MIT", "engines": { @@ -413,8 +350,6 @@ }, "node_modules/@babel/helper-replace-supers": { "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", - "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", "dev": true, "license": "MIT", "dependencies": { @@ -431,8 +366,6 @@ }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "dev": true, "license": "MIT", "dependencies": { @@ -445,8 +378,6 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -454,8 +385,6 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -463,8 +392,6 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "license": "MIT", "engines": { @@ -473,8 +400,6 @@ }, "node_modules/@babel/helpers": { "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", "dev": true, "license": "MIT", "dependencies": { @@ -487,8 +412,6 @@ }, "node_modules/@babel/parser": { "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", "license": "MIT", "dependencies": { "@babel/types": "^7.26.9" @@ -502,8 +425,6 @@ }, "node_modules/@babel/plugin-proposal-decorators": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz", - "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==", "dev": true, "license": "MIT", "dependencies": { @@ -520,8 +441,6 @@ }, "node_modules/@babel/plugin-syntax-decorators": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", - "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", "dev": true, "license": "MIT", "dependencies": { @@ -536,8 +455,6 @@ }, "node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { @@ -552,8 +469,6 @@ }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "license": "MIT", "dependencies": { @@ -565,8 +480,6 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "license": "MIT", "dependencies": { @@ -581,8 +494,6 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -597,8 +508,6 @@ }, "node_modules/@babel/plugin-transform-typescript": { "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz", - "integrity": "sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==", "dev": true, "license": "MIT", "dependencies": { @@ -617,8 +526,6 @@ }, "node_modules/@babel/template": { "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, "license": "MIT", "dependencies": { @@ -632,8 +539,6 @@ }, "node_modules/@babel/traverse": { "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", - "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", "dev": true, "license": "MIT", "dependencies": { @@ -651,8 +556,6 @@ }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "license": "MIT", "engines": { @@ -661,8 +564,6 @@ }, "node_modules/@babel/types": { "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -674,8 +575,6 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "license": "MIT", "dependencies": { @@ -687,8 +586,6 @@ }, "node_modules/@csstools/color-helpers": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz", - "integrity": "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==", "dev": true, "funding": [ { @@ -707,8 +604,6 @@ }, "node_modules/@csstools/css-calc": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.1.tgz", - "integrity": "sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==", "dev": true, "funding": [ { @@ -731,8 +626,6 @@ }, "node_modules/@csstools/css-color-parser": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz", - "integrity": "sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==", "dev": true, "funding": [ { @@ -759,8 +652,6 @@ }, "node_modules/@csstools/css-parser-algorithms": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", "dev": true, "funding": [ { @@ -782,8 +673,6 @@ }, "node_modules/@csstools/css-tokenizer": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", "dev": true, "funding": [ { @@ -800,298 +689,8 @@ "node": ">=18" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", - "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", - "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", - "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", - "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", - "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", - "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", - "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", - "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", - "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", - "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", - "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", - "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", - "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", - "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", - "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", - "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/linux-x64": { "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", - "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], @@ -1106,154 +705,8 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", - "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", - "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", - "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", - "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", - "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", - "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", - "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", - "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=18" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "license": "MIT", "dependencies": { @@ -1271,8 +724,6 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -1281,8 +732,6 @@ }, "node_modules/@eslint/compat": { "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.6.tgz", - "integrity": "sha512-k7HNCqApoDHM6XzT30zGoETj+D+uUcZUb+IVAJmar3u6bvHf7hhHJcWx09QHj4/a2qrKZMWU0E16tvkiAdv06Q==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1299,8 +748,6 @@ }, "node_modules/@eslint/config-array": { "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1314,8 +761,6 @@ }, "node_modules/@eslint/config-array/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": { @@ -1325,8 +770,6 @@ }, "node_modules/@eslint/config-array/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": { @@ -1338,8 +781,6 @@ }, "node_modules/@eslint/core": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz", - "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1351,8 +792,6 @@ }, "node_modules/@eslint/eslintrc": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -1375,8 +814,6 @@ }, "node_modules/@eslint/eslintrc/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": { @@ -1386,8 +823,6 @@ }, "node_modules/@eslint/eslintrc/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": { @@ -1399,8 +834,6 @@ }, "node_modules/@eslint/js": { "version": "9.20.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz", - "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==", "dev": true, "license": "MIT", "engines": { @@ -1409,8 +842,6 @@ }, "node_modules/@eslint/object-schema": { "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1419,8 +850,6 @@ }, "node_modules/@eslint/plugin-kit": { "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.6.tgz", - "integrity": "sha512-+0TjwR1eAUdZtvv/ir1mGX+v0tUoR3VEPB8Up0LLJC+whRW0GgBBtpbOkg/a/U4Dxa6l5a3l9AJ1aWIQVyoWJA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1433,14 +862,11 @@ }, "node_modules/@gar/promisify": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", "optional": true }, "node_modules/@humanfs/core": { "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1449,8 +875,6 @@ }, "node_modules/@humanfs/node": { "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1463,8 +887,6 @@ }, "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1477,8 +899,6 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1491,8 +911,6 @@ }, "node_modules/@humanwhocodes/retry": { "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", - "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1507,7 +925,6 @@ "version": "10.0.5", "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-10.0.5.tgz", "integrity": "sha512-F3snDTQs0MdvnnyzTDTVkOYVAZOE/MHwRvF7mn7Jw1yuih4NrFYLNYIymGlLmq4HU2iIdzYsZ7f47bOcwY73XQ==", - "license": "MIT", "dependencies": { "@intlify/message-compiler": "10.0.5", "@intlify/shared": "10.0.5" @@ -1523,7 +940,6 @@ "version": "10.0.5", "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-10.0.5.tgz", "integrity": "sha512-6GT1BJ852gZ0gItNZN2krX5QAmea+cmdjMvsWohArAZ3GmHdnNANEcF9JjPXAMRtQ6Ux5E269ymamg/+WU6tQA==", - "license": "MIT", "dependencies": { "@intlify/shared": "10.0.5", "source-map-js": "^1.0.2" @@ -1539,7 +955,6 @@ "version": "10.0.5", "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-10.0.5.tgz", "integrity": "sha512-bmsP4L2HqBF6i6uaMqJMcFBONVjKt+siGluRq4Ca4C0q7W2eMaVZr8iCgF9dKbcVXutftkC7D6z2SaSMmLiDyA==", - "license": "MIT", "engines": { "node": ">= 16" }, @@ -1549,8 +964,6 @@ }, "node_modules/@isaacs/cliui": { "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "license": "ISC", "dependencies": { @@ -1565,95 +978,8 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@jercle/yargonaut": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@jercle/yargonaut/-/yargonaut-1.1.5.tgz", - "integrity": "sha512-zBp2myVvBHp1UaJsNTyS6q4UDKT7eRiqTS4oNTS6VQMd6mpxYOdbeK4pY279cDCdakGy6hG0J3ejoXZVsPwHqw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1664,8 +990,6 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "license": "MIT", "dependencies": { @@ -1679,8 +1003,6 @@ }, "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1690,8 +1012,6 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { @@ -1700,8 +1020,6 @@ }, "node_modules/@jridgewell/set-array": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "license": "MIT", "engines": { @@ -1710,14 +1028,10 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1727,8 +1041,6 @@ }, "node_modules/@mikro-orm/cli": { "version": "6.4.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.4.6.tgz", - "integrity": "sha512-sTMoDSJrnHZBT+ZAG40OeZwR9zRTYHtaaub9OoMM2CrxfI1KeiNqL/XFB4LaM5SVRAbnoEFpMJwQ8KS+5NcN9w==", "dev": true, "license": "MIT", "dependencies": { @@ -1749,8 +1061,6 @@ }, "node_modules/@mikro-orm/core": { "version": "6.4.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.4.6.tgz", - "integrity": "sha512-xVm/ALG/3vTMgh6SrvojJ6jjMa0s2hNzWN0triDB16BaNdLwWE4aAaAe+3CuoMFqJAArSOUISTEjExbzELB1ZA==", "license": "MIT", "dependencies": { "dataloader": "2.2.3", @@ -1770,8 +1080,6 @@ }, "node_modules/@mikro-orm/knex": { "version": "6.4.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.4.6.tgz", - "integrity": "sha512-o6t67tFH/GuPZCCEtKbTTL8HDXNgB2ITjButCTZLwteL0qI9yE/f7K6K+dEUKW+hAL3KRvc2BQeumvCVWFeISg==", "license": "MIT", "dependencies": { "fs-extra": "11.3.0", @@ -1801,8 +1109,6 @@ }, "node_modules/@mikro-orm/postgresql": { "version": "6.4.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/postgresql/-/postgresql-6.4.6.tgz", - "integrity": "sha512-ZcuGp6n/SPzkHPANksjdLPyeu6jT7WCg3ueNViVrxdsguCi+/grz4I+hbOQDXV8uNHCAUOw6+WP2ndcVEYkZZQ==", "license": "MIT", "dependencies": { "@mikro-orm/knex": "6.4.6", @@ -1820,8 +1126,6 @@ }, "node_modules/@mikro-orm/reflection": { "version": "6.4.6", - "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.4.6.tgz", - "integrity": "sha512-7mL7HFVnaOOhDNgLjjndWyeJUtOl2wKn0spSqB8uRjS4XtwNEGVZNkW5YD1t/x7TJ99wUhe+oRDiySciiJSeBQ==", "license": "MIT", "dependencies": { "globby": "11.1.0", @@ -1834,10 +1138,24 @@ "@mikro-orm/core": "^6.0.0" } }, + "node_modules/@mikro-orm/sqlite": { + "version": "6.4.6", + "license": "MIT", + "dependencies": { + "@mikro-orm/knex": "6.4.6", + "fs-extra": "11.3.0", + "sqlite3": "5.1.7", + "sqlstring-sqlite": "0.1.1" + }, + "engines": { + "node": ">= 18.12.0" + }, + "peerDependencies": { + "@mikro-orm/core": "^6.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -1849,8 +1167,6 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "license": "MIT", "engines": { "node": ">= 8" @@ -1858,8 +1174,6 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -1871,8 +1185,7 @@ }, "node_modules/@npmcli/fs": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", "optional": true, "dependencies": { "@gar/promisify": "^1.0.1", @@ -1881,9 +1194,7 @@ }, "node_modules/@npmcli/move-file": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", "optional": true, "dependencies": { "mkdirp": "^1.0.4", @@ -1895,15 +1206,11 @@ }, "node_modules/@one-ini/wasm": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", - "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", "dev": true, "license": "MIT" }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", "optional": true, @@ -1913,8 +1220,6 @@ }, "node_modules/@pkgr/core": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, "license": "MIT", "engines": { @@ -1926,8 +1231,6 @@ }, "node_modules/@playwright/test": { "version": "1.50.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.1.tgz", - "integrity": "sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1942,15 +1245,11 @@ }, "node_modules/@polka/url": { "version": "1.0.0-next.28", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", - "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true, "license": "MIT" }, "node_modules/@rollup/pluginutils": { "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", - "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1970,17 +1269,8 @@ } } }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, "node_modules/@rollup/pluginutils/node_modules/picomatch": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, "license": "MIT", "engines": { @@ -1990,206 +1280,8 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", - "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", - "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", - "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", - "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", - "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", - "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", - "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", - "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", - "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", - "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz", - "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz", - "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", - "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", - "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", - "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", "cpu": [ "x64" ], @@ -2202,8 +1294,6 @@ }, "node_modules/@rollup/rollup-linux-x64-musl": { "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", - "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", "cpu": [ "x64" ], @@ -2214,59 +1304,13 @@ "linux" ] }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", - "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", - "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", - "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@sec-ant/readable-stream": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", - "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", "dev": true, "license": "MIT" }, "node_modules/@sindresorhus/merge-streams": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", "dev": true, "license": "MIT", "engines": { @@ -2278,8 +1322,7 @@ }, "node_modules/@tootallnate/once": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", "optional": true, "engines": { "node": ">= 6" @@ -2287,8 +1330,6 @@ }, "node_modules/@ts-morph/common": { "version": "0.26.1", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.26.1.tgz", - "integrity": "sha512-Sn28TGl/4cFpcM+jwsH1wLncYq3FtN/BIpem+HOygfBWPT5pAeS5dB4VFVzV8FbnOKHpDLZmvAl4AjPEev5idA==", "license": "MIT", "dependencies": { "fast-glob": "^3.3.2", @@ -2298,43 +1339,31 @@ }, "node_modules/@tsconfig/node10": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node22": { "version": "22.0.0", - "resolved": "https://registry.npmjs.org/@tsconfig/node22/-/node22-22.0.0.tgz", - "integrity": "sha512-twLQ77zevtxobBOD4ToAtVmuYrpeYUh3qh+TEp+08IWhpsrIflVHqQ1F1CiPxQGL7doCdBIOOCF+1Tm833faNg==", "dev": true, "license": "MIT" }, "node_modules/@types/body-parser": { "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, "license": "MIT", "dependencies": { @@ -2344,8 +1373,6 @@ }, "node_modules/@types/connect": { "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, "license": "MIT", "dependencies": { @@ -2354,22 +1381,16 @@ }, "node_modules/@types/eslint-config-prettier": { "version": "6.11.3", - "resolved": "https://registry.npmjs.org/@types/eslint-config-prettier/-/eslint-config-prettier-6.11.3.tgz", - "integrity": "sha512-3wXCiM8croUnhg9LdtZUJQwNcQYGWxxdOWDjPe1ykCqJFPVpzAKfs/2dgSoCtAvdPeaponcWPI7mPcGGp9dkKQ==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, "license": "MIT" }, "node_modules/@types/express": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", - "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2381,8 +1402,6 @@ }, "node_modules/@types/express-serve-static-core": { "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", - "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", "dev": true, "license": "MIT", "dependencies": { @@ -2394,21 +1413,16 @@ }, "node_modules/@types/http-errors": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true, "license": "MIT" }, "node_modules/@types/js-yaml": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "license": "MIT" + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==" }, "node_modules/@types/jsdom": { "version": "21.1.7", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", - "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", "dev": true, "license": "MIT", "dependencies": { @@ -2419,22 +1433,16 @@ }, "node_modules/@types/json-schema": { "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, "node_modules/@types/mime": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { "version": "22.13.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz", - "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==", "dev": true, "license": "MIT", "dependencies": { @@ -2443,22 +1451,16 @@ }, "node_modules/@types/qs": { "version": "6.9.18", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", - "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", "dev": true, "license": "MIT" }, "node_modules/@types/range-parser": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true, "license": "MIT" }, "node_modules/@types/send": { "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dev": true, "license": "MIT", "dependencies": { @@ -2468,8 +1470,6 @@ }, "node_modules/@types/serve-static": { "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dev": true, "license": "MIT", "dependencies": { @@ -2480,15 +1480,11 @@ }, "node_modules/@types/tough-cookie": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true, "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.1.tgz", - "integrity": "sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==", "dev": true, "license": "MIT", "dependencies": { @@ -2517,8 +1513,6 @@ }, "node_modules/@typescript-eslint/parser": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.1.tgz", - "integrity": "sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2542,8 +1536,6 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.1.tgz", - "integrity": "sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2560,8 +1552,6 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.1.tgz", - "integrity": "sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==", "dev": true, "license": "MIT", "dependencies": { @@ -2584,8 +1574,6 @@ }, "node_modules/@typescript-eslint/types": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.1.tgz", - "integrity": "sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==", "dev": true, "license": "MIT", "engines": { @@ -2598,8 +1586,6 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.1.tgz", - "integrity": "sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==", "dev": true, "license": "MIT", "dependencies": { @@ -2625,8 +1611,6 @@ }, "node_modules/@typescript-eslint/utils": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.1.tgz", - "integrity": "sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2649,8 +1633,6 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.1.tgz", - "integrity": "sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==", "dev": true, "license": "MIT", "dependencies": { @@ -2667,8 +1649,6 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2680,8 +1660,6 @@ }, "node_modules/@vitejs/plugin-vue": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz", - "integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==", "dev": true, "license": "MIT", "engines": { @@ -2694,8 +1672,6 @@ }, "node_modules/@vitest/eslint-plugin": { "version": "1.1.31", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.31.tgz", - "integrity": "sha512-xlsLr+e+AXZ/00eVZCtNmMeCJoJaRCoLDiAgLcxgQjSS1EertieB2MUHf8xIqPKs9lECc/UpL+y1xDcpvi02hw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -2715,8 +1691,6 @@ }, "node_modules/@vitest/expect": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.6.tgz", - "integrity": "sha512-zBduHf/ja7/QRX4HdP1DSq5XrPgdN+jzLOwaTq/0qZjYfgETNFCKf9nOAp2j3hmom3oTbczuUzrzg9Hafh7hNg==", "dev": true, "license": "MIT", "dependencies": { @@ -2731,8 +1705,6 @@ }, "node_modules/@vitest/mocker": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.6.tgz", - "integrity": "sha512-KPztr4/tn7qDGZfqlSPQoF2VgJcKxnDNhmfR3VgZ6Fy1bO8T9Fc1stUiTXtqz0yG24VpD00pZP5f8EOFknjNuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2756,10 +1728,16 @@ } } }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/@vitest/pretty-format": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.6.tgz", - "integrity": "sha512-Zyctv3dbNL+67qtHfRnUE/k8qxduOamRfAL1BurEIQSyOEFffoMvx2pnDSSbKAAVxY0Ej2J/GH2dQKI0W2JyVg==", "dev": true, "license": "MIT", "dependencies": { @@ -2771,8 +1749,6 @@ }, "node_modules/@vitest/runner": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.6.tgz", - "integrity": "sha512-JopP4m/jGoaG1+CBqubV/5VMbi7L+NQCJTu1J1Pf6YaUbk7bZtaq5CX7p+8sY64Sjn1UQ1XJparHfcvTTdu9cA==", "dev": true, "license": "MIT", "dependencies": { @@ -2785,8 +1761,6 @@ }, "node_modules/@vitest/snapshot": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.6.tgz", - "integrity": "sha512-qKSmxNQwT60kNwwJHMVwavvZsMGXWmngD023OHSgn873pV0lylK7dwBTfYP7e4URy5NiBCHHiQGA9DHkYkqRqg==", "dev": true, "license": "MIT", "dependencies": { @@ -2800,8 +1774,6 @@ }, "node_modules/@vitest/spy": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.6.tgz", - "integrity": "sha512-HfOGx/bXtjy24fDlTOpgiAEJbRfFxoX3zIGagCqACkFKKZ/TTOE6gYMKXlqecvxEndKFuNHcHqP081ggZ2yM0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2813,8 +1785,6 @@ }, "node_modules/@vitest/utils": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.6.tgz", - "integrity": "sha512-18ktZpf4GQFTbf9jK543uspU03Q2qya7ZGya5yiZ0Gx0nnnalBvd5ZBislbl2EhLjM8A8rt4OilqKG7QwcGkvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2828,8 +1798,6 @@ }, "node_modules/@volar/language-core": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.11.tgz", - "integrity": "sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==", "dev": true, "license": "MIT", "dependencies": { @@ -2838,15 +1806,11 @@ }, "node_modules/@volar/source-map": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.11.tgz", - "integrity": "sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==", "dev": true, "license": "MIT" }, "node_modules/@volar/typescript": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.11.tgz", - "integrity": "sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==", "dev": true, "license": "MIT", "dependencies": { @@ -2857,15 +1821,11 @@ }, "node_modules/@vue/babel-helper-vue-transform-on": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.2.5.tgz", - "integrity": "sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==", "dev": true, "license": "MIT" }, "node_modules/@vue/babel-plugin-jsx": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.2.5.tgz", - "integrity": "sha512-zTrNmOd4939H9KsRIGmmzn3q2zvv1mjxkYZHgqHZgDrXz5B1Q3WyGEjO2f+JrmKghvl1JIRcvo63LgM1kH5zFg==", "dev": true, "license": "MIT", "dependencies": { @@ -2891,8 +1851,6 @@ }, "node_modules/@vue/babel-plugin-resolve-type": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.2.5.tgz", - "integrity": "sha512-U/ibkQrf5sx0XXRnUZD1mo5F7PkpKyTbfXM3a3rC4YnUz6crHEz9Jg09jzzL6QYlXNto/9CePdOg/c87O4Nlfg==", "dev": true, "license": "MIT", "dependencies": { @@ -2908,8 +1866,6 @@ }, "node_modules/@vue/compiler-core": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", - "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", "license": "MIT", "dependencies": { "@babel/parser": "^7.25.3", @@ -2919,16 +1875,8 @@ "source-map-js": "^1.2.0" } }, - "node_modules/@vue/compiler-core/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "license": "MIT" - }, "node_modules/@vue/compiler-dom": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", - "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", "license": "MIT", "dependencies": { "@vue/compiler-core": "3.5.13", @@ -2937,8 +1885,6 @@ }, "node_modules/@vue/compiler-sfc": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", - "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", "license": "MIT", "dependencies": { "@babel/parser": "^7.25.3", @@ -2952,16 +1898,8 @@ "source-map-js": "^1.2.0" } }, - "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "license": "MIT" - }, "node_modules/@vue/compiler-ssr": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", - "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", "license": "MIT", "dependencies": { "@vue/compiler-dom": "3.5.13", @@ -2970,8 +1908,6 @@ }, "node_modules/@vue/compiler-vue2": { "version": "2.7.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", - "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", "dev": true, "license": "MIT", "dependencies": { @@ -2981,14 +1917,10 @@ }, "node_modules/@vue/devtools-api": { "version": "6.6.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", - "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "license": "MIT" }, "node_modules/@vue/devtools-core": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.7.2.tgz", - "integrity": "sha512-lexREWj1lKi91Tblr38ntSsy6CvI8ba7u+jmwh2yruib/ltLUcsIzEjCnrkh1yYGGIKXbAuYV2tOG10fGDB9OQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3005,8 +1937,6 @@ }, "node_modules/@vue/devtools-core/node_modules/nanoid": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.0.tgz", - "integrity": "sha512-zDAl/llz8Ue/EblwSYwdxGBYfj46IM1dhjVi8dyp9LQffoIGxJEAHj2oeZ4uNcgycSRcQ83CnfcZqEJzVDLcDw==", "dev": true, "funding": [ { @@ -3024,8 +1954,6 @@ }, "node_modules/@vue/devtools-kit": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz", - "integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3040,8 +1968,6 @@ }, "node_modules/@vue/devtools-shared": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz", - "integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==", "dev": true, "license": "MIT", "dependencies": { @@ -3050,8 +1976,6 @@ }, "node_modules/@vue/eslint-config-prettier": { "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-10.2.0.tgz", - "integrity": "sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==", "dev": true, "license": "MIT", "dependencies": { @@ -3065,8 +1989,6 @@ }, "node_modules/@vue/eslint-config-typescript": { "version": "14.4.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.4.0.tgz", - "integrity": "sha512-daU+eAekEeVz3CReE4PRW25fe+OJDKwE28jHN6LimDEnuFMbJ6H4WGogEpNof276wVP6UvzOeJQfLFjB5mW29A==", "dev": true, "license": "MIT", "dependencies": { @@ -3091,8 +2013,6 @@ }, "node_modules/@vue/language-core": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.2.tgz", - "integrity": "sha512-QotO41kurE5PLf3vrNgGTk3QswO2PdUFjBwNiOi7zMmGhwb25PSTh9hD1MCgKC06AVv+8sZQvlL3Do4TTVHSiQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3116,8 +2036,6 @@ }, "node_modules/@vue/reactivity": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", - "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", "license": "MIT", "dependencies": { "@vue/shared": "3.5.13" @@ -3125,8 +2043,6 @@ }, "node_modules/@vue/runtime-core": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", - "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", "license": "MIT", "dependencies": { "@vue/reactivity": "3.5.13", @@ -3135,8 +2051,6 @@ }, "node_modules/@vue/runtime-dom": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", - "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", "license": "MIT", "dependencies": { "@vue/reactivity": "3.5.13", @@ -3147,8 +2061,6 @@ }, "node_modules/@vue/server-renderer": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", - "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", "license": "MIT", "dependencies": { "@vue/compiler-ssr": "3.5.13", @@ -3160,14 +2072,10 @@ }, "node_modules/@vue/shared": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", - "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", "license": "MIT" }, "node_modules/@vue/test-utils": { "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz", - "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", "dev": true, "license": "MIT", "dependencies": { @@ -3177,8 +2085,6 @@ }, "node_modules/@vue/tsconfig": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.7.0.tgz", - "integrity": "sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -3196,8 +2102,6 @@ }, "node_modules/abbrev": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.0.tgz", - "integrity": "sha512-+/kfrslGQ7TNV2ecmQwMJj/B65g5KVq1/L3SGVZ3tCYGqlzFuFCGBZJtMP99wH3NpEUyAjn0zPdPUg0D+DwrOA==", "dev": true, "license": "ISC", "engines": { @@ -3206,8 +2110,6 @@ }, "node_modules/accepts": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "license": "MIT", "dependencies": { "mime-types": "^3.0.0", @@ -3219,8 +2121,6 @@ }, "node_modules/acorn": { "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { @@ -3232,8 +2132,6 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -3242,8 +2140,6 @@ }, "node_modules/acorn-walk": { "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", "dependencies": { @@ -3255,8 +2151,6 @@ }, "node_modules/agent-base": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "dev": true, "license": "MIT", "engines": { @@ -3265,8 +2159,7 @@ }, "node_modules/agentkeepalive": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", "optional": true, "dependencies": { "humanize-ms": "^1.2.1" @@ -3277,8 +2170,7 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", "optional": true, "dependencies": { "clean-stack": "^2.0.0", @@ -3290,8 +2182,6 @@ }, "node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { @@ -3306,26 +2196,23 @@ } }, "node_modules/alien-signals": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-1.0.4.tgz", - "integrity": "sha512-DJqqQD3XcsaQcQ1s+iE2jDUZmmQpXwHiR6fCAim/w87luaW+vmLY8fMlrdkmRwzaFXhkxf3rqPCR59tKVv1MDw==", + "version": "1.0.3", "dev": true, "license": "MIT" }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "6.1.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -3340,15 +2227,12 @@ }, "node_modules/aproba": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC", "optional": true }, "node_modules/are-we-there-yet": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", + "license": "ISC", "optional": true, "dependencies": { "delegates": "^1.0.0", @@ -3360,21 +2244,15 @@ }, "node_modules/arg": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true, "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, "node_modules/array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "license": "MIT", "engines": { "node": ">=8" @@ -3382,8 +2260,6 @@ }, "node_modules/assertion-error": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { @@ -3392,15 +2268,12 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/axios": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz", "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==", - "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -3409,14 +2282,10 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -3430,36 +2299,27 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/bindings": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", "dependencies": { "file-uri-to-path": "1.0.0" } }, "node_modules/birpc": { "version": "0.2.19", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.19.tgz", - "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" } }, - "node_modules/bmp-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", - "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", - "license": "MIT" - }, "node_modules/bl": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -3468,8 +2328,6 @@ }, "node_modules/body-parser": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.1.0.tgz", - "integrity": "sha512-/hPxh61E+ll0Ujp24Ilm64cykicul1ypfwjVttduAiEdtnJFvLePSrIPk+HMImtNv5270wOGCb1Tns2rybMkoQ==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", @@ -3488,8 +2346,6 @@ }, "node_modules/body-parser/node_modules/qs": { "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -3503,15 +2359,11 @@ }, "node_modules/boolbase": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true, "license": "ISC" }, "node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -3519,8 +2371,6 @@ }, "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -3531,8 +2381,6 @@ }, "node_modules/browserslist": { "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -3564,8 +2412,6 @@ }, "node_modules/buffer": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -3580,6 +2426,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -3587,8 +2434,6 @@ }, "node_modules/bundle-name": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3603,8 +2448,6 @@ }, "node_modules/bytes": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -3612,8 +2455,6 @@ }, "node_modules/cac": { "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "license": "MIT", "engines": { @@ -3622,8 +2463,7 @@ }, "node_modules/cacache": { "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", "optional": true, "dependencies": { "@npmcli/fs": "^1.0.0", @@ -3651,8 +2491,7 @@ }, "node_modules/cacache/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==", + "license": "MIT", "optional": true, "dependencies": { "balanced-match": "^1.0.0", @@ -3661,9 +2500,7 @@ }, "node_modules/cacache/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", + "license": "ISC", "optional": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -3682,8 +2519,7 @@ }, "node_modules/cacache/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -3694,8 +2530,7 @@ }, "node_modules/cacache/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "optional": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -3706,8 +2541,7 @@ }, "node_modules/cacache/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -3718,14 +2552,11 @@ }, "node_modules/cacache/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -3737,8 +2568,6 @@ }, "node_modules/call-bound": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -3753,8 +2582,6 @@ }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { @@ -3763,8 +2590,6 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001700", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz", - "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==", "dev": true, "funding": [ { @@ -3784,8 +2609,6 @@ }, "node_modules/chai": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", "dev": true, "license": "MIT", "dependencies": { @@ -3801,8 +2624,6 @@ }, "node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -3818,8 +2639,6 @@ }, "node_modules/check-error": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "license": "MIT", "engines": { @@ -3828,16 +2647,14 @@ }, "node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/clean-stack": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", "optional": true, "engines": { "node": ">=6" @@ -3845,8 +2662,6 @@ }, "node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "license": "ISC", "dependencies": { @@ -3858,16 +2673,65 @@ "node": ">=12" } }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/code-block-writer": { "version": "13.0.3", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", - "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3879,15 +2743,12 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/color-support": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", "optional": true, "bin": { "color-support": "bin.js" @@ -3895,14 +2756,10 @@ }, "node_modules/colorette": { "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -3913,8 +2770,6 @@ }, "node_modules/commander": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "license": "MIT", "engines": { "node": ">=14" @@ -3922,15 +2777,11 @@ }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "devOptional": true, "license": "MIT" }, "node_modules/config-chain": { "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3940,14 +2791,11 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", "optional": true }, "node_modules/content-disposition": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -3958,8 +2806,6 @@ }, "node_modules/content-type": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3967,15 +2813,11 @@ }, "node_modules/convert-source-map": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/cookie": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3983,8 +2825,6 @@ }, "node_modules/cookie-signature": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", "engines": { "node": ">=6.6.0" @@ -3992,8 +2832,6 @@ }, "node_modules/copy-anything": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", "dev": true, "license": "MIT", "dependencies": { @@ -4008,15 +2846,11 @@ }, "node_modules/create-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -4030,8 +2864,6 @@ }, "node_modules/cssesc": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "license": "MIT", "bin": { @@ -4043,8 +2875,6 @@ }, "node_modules/cssstyle": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz", - "integrity": "sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==", "dev": true, "license": "MIT", "dependencies": { @@ -4057,14 +2887,10 @@ }, "node_modules/csstype": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, "node_modules/data-urls": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, "license": "MIT", "dependencies": { @@ -4077,21 +2903,15 @@ }, "node_modules/dataloader": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.3.tgz", - "integrity": "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==", "license": "MIT" }, "node_modules/de-indent": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", "dev": true, "license": "MIT" }, "node_modules/debug": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -4107,15 +2927,12 @@ }, "node_modules/decimal.js": { "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", "dev": true, "license": "MIT" }, "node_modules/decompress-response": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -4128,8 +2945,6 @@ }, "node_modules/deep-eql": { "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", "engines": { @@ -4138,23 +2953,18 @@ }, "node_modules/deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, "node_modules/default-browser": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, "license": "MIT", "dependencies": { @@ -4170,8 +2980,6 @@ }, "node_modules/default-browser-id": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", "dev": true, "license": "MIT", "engines": { @@ -4183,8 +2991,6 @@ }, "node_modules/define-lazy-prop": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "license": "MIT", "engines": { @@ -4196,8 +3002,6 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -4205,14 +3009,11 @@ }, "node_modules/delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", "optional": true }, "node_modules/depd": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -4220,8 +3021,6 @@ }, "node_modules/destroy": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "license": "MIT", "engines": { "node": ">= 0.8", @@ -4230,16 +3029,13 @@ }, "node_modules/detect-libc": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", "engines": { "node": ">=8" } }, "node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -4248,8 +3044,6 @@ }, "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "license": "MIT", "dependencies": { "path-type": "^4.0.0" @@ -4260,8 +3054,6 @@ }, "node_modules/dotenv": { "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -4272,8 +3064,6 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -4294,15 +3084,11 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, "license": "MIT" }, "node_modules/editorconfig": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", - "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4320,8 +3106,6 @@ }, "node_modules/editorconfig/node_modules/minimatch": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, "license": "ISC", "dependencies": { @@ -4336,28 +3120,20 @@ }, "node_modules/ee-first": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, "node_modules/electron-to-chromium": { "version": "1.5.102", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz", - "integrity": "sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==", "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "9.2.2", "dev": true, "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -4365,8 +3141,7 @@ }, "node_modules/encoding": { "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", "optional": true, "dependencies": { "iconv-lite": "^0.6.2" @@ -4374,8 +3149,7 @@ }, "node_modules/encoding/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -4386,16 +3160,13 @@ }, "node_modules/end-of-stream": { "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/entities": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -4406,8 +3177,7 @@ }, "node_modules/env-paths": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", "optional": true, "engines": { "node": ">=6" @@ -4415,14 +3185,11 @@ }, "node_modules/err-code": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", "optional": true }, "node_modules/error-stack-parser-es": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz", - "integrity": "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==", "dev": true, "license": "MIT", "funding": { @@ -4431,8 +3198,6 @@ }, "node_modules/es-define-property": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -4440,8 +3205,6 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -4449,15 +3212,11 @@ }, "node_modules/es-module-lexer": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -4468,8 +3227,6 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -4483,8 +3240,6 @@ }, "node_modules/esbuild": { "version": "0.25.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", - "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4524,8 +3279,6 @@ }, "node_modules/escalade": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", "engines": { "node": ">=6" @@ -4533,14 +3286,10 @@ }, "node_modules/escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { @@ -4552,8 +3301,6 @@ }, "node_modules/eslint": { "version": "9.20.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz", - "integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==", "dev": true, "license": "MIT", "dependencies": { @@ -4612,8 +3359,6 @@ }, "node_modules/eslint-config-prettier": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.1.tgz", - "integrity": "sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==", "dev": true, "license": "MIT", "bin": { @@ -4625,8 +3370,6 @@ }, "node_modules/eslint-plugin-playwright": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.2.0.tgz", - "integrity": "sha512-qSQpAw7RcSzE3zPp8FMGkthaCWovHZ/BsXtpmnGax9vQLIovlh1bsZHEa2+j2lv9DWhnyeLM/qZmp7ffQZfQvg==", "dev": true, "license": "MIT", "workspaces": [ @@ -4644,8 +3387,6 @@ }, "node_modules/eslint-plugin-playwright/node_modules/globals": { "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4660,8 +3401,6 @@ }, "node_modules/eslint-plugin-prettier": { "version": "5.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", - "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, "license": "MIT", "dependencies": { @@ -4691,8 +3430,6 @@ }, "node_modules/eslint-plugin-vue": { "version": "9.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.32.0.tgz", - "integrity": "sha512-b/Y05HYmnB/32wqVcjxjHZzNpwxj1onBOvqW89W+V+XNG1dRuaFbNd3vT9CLbr2LXjEoq+3vn8DanWf7XU22Ug==", "dev": true, "license": "MIT", "dependencies": { @@ -4714,8 +3451,6 @@ }, "node_modules/eslint-plugin-vue/node_modules/globals": { "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4730,8 +3465,6 @@ }, "node_modules/eslint-scope": { "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4747,8 +3480,6 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4760,8 +3491,6 @@ }, "node_modules/eslint/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": { @@ -4771,8 +3500,6 @@ }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4784,8 +3511,6 @@ }, "node_modules/eslint/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": { @@ -4797,8 +3522,6 @@ }, "node_modules/esm": { "version": "3.2.25", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", "license": "MIT", "engines": { "node": ">=6" @@ -4806,8 +3529,6 @@ }, "node_modules/espree": { "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4824,8 +3545,6 @@ }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4837,8 +3556,6 @@ }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -4850,8 +3567,6 @@ }, "node_modules/esquery": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -4863,8 +3578,6 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4876,8 +3589,6 @@ }, "node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -4885,19 +3596,11 @@ } }, "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } + "version": "2.0.2", + "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -4906,8 +3609,6 @@ }, "node_modules/etag": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -4915,8 +3616,6 @@ }, "node_modules/execa": { "version": "9.5.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", - "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4942,16 +3641,13 @@ }, "node_modules/expand-template": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", "engines": { "node": ">=6" } }, "node_modules/expect-type": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", - "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4960,8 +3656,6 @@ }, "node_modules/express": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.0.1.tgz", - "integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==", "license": "MIT", "dependencies": { "accepts": "^2.0.0", @@ -5003,8 +3697,6 @@ }, "node_modules/express/node_modules/debug": { "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -5020,28 +3712,20 @@ }, "node_modules/express/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true, "license": "Apache-2.0" }, "node_modules/fast-glob": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -5056,8 +3740,6 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -5068,22 +3750,16 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, "node_modules/fastq": { "version": "1.19.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", - "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -5091,8 +3767,6 @@ }, "node_modules/figlet": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.0.tgz", - "integrity": "sha512-chzvGjd+Sp7KUvPHZv6EXV5Ir3Q7kYNpCr4aHrRW79qFtTefmQZNny+W1pW9kf5zeE6dikku2W50W/wAH2xWgw==", "dev": true, "license": "MIT", "bin": { @@ -5104,8 +3778,6 @@ }, "node_modules/figures": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", "dev": true, "license": "MIT", "dependencies": { @@ -5120,8 +3792,6 @@ }, "node_modules/file-entry-cache": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5133,13 +3803,10 @@ }, "node_modules/file-uri-to-path": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "license": "MIT" }, "node_modules/fill-range": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -5150,8 +3817,6 @@ }, "node_modules/finalhandler": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.0.0.tgz", - "integrity": "sha512-MX6Zo2adDViYh+GcxxB1dpO43eypOGUOL12rLCOTMQv/DfIbpSJUy4oQIIZhVZkH9e+bZWKMon0XHFEju16tkQ==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -5168,8 +3833,6 @@ }, "node_modules/finalhandler/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -5177,8 +3840,6 @@ }, "node_modules/finalhandler/node_modules/encodeurl": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -5186,14 +3847,10 @@ }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { @@ -5209,8 +3866,6 @@ }, "node_modules/flat-cache": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { @@ -5223,8 +3878,6 @@ }, "node_modules/flatted": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, "license": "ISC" }, @@ -5238,7 +3891,6 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], - "license": "MIT", "engines": { "node": ">=4.0" }, @@ -5250,8 +3902,6 @@ }, "node_modules/foreground-child": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, "license": "ISC", "dependencies": { @@ -5267,8 +3917,6 @@ }, "node_modules/form-data": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -5282,8 +3930,6 @@ }, "node_modules/form-data/node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -5291,8 +3937,6 @@ }, "node_modules/form-data/node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -5303,8 +3947,6 @@ }, "node_modules/forwarded": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -5312,8 +3954,6 @@ }, "node_modules/fresh": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -5321,13 +3961,10 @@ }, "node_modules/fs-constants": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + "license": "MIT" }, "node_modules/fs-extra": { "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -5340,8 +3977,7 @@ }, "node_modules/fs-minipass": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -5351,8 +3987,7 @@ }, "node_modules/fs-minipass/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -5362,34 +3997,15 @@ }, "node_modules/fs-minipass/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", "optional": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5397,9 +4013,7 @@ }, "node_modules/gauge": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", + "license": "ISC", "optional": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", @@ -5417,8 +4031,7 @@ }, "node_modules/gauge/node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "optional": true, "engines": { "node": ">=8" @@ -5426,20 +4039,17 @@ }, "node_modules/gauge/node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", "optional": true }, "node_modules/gauge/node_modules/signal-exit": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", "optional": true }, "node_modules/gauge/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "optional": true, "dependencies": { "emoji-regex": "^8.0.0", @@ -5452,8 +4062,7 @@ }, "node_modules/gauge/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "optional": true, "dependencies": { "ansi-regex": "^5.0.1" @@ -5464,8 +4073,6 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", "engines": { @@ -5474,8 +4081,6 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "license": "ISC", "engines": { @@ -5484,8 +4089,6 @@ }, "node_modules/get-intrinsic": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -5508,8 +4111,6 @@ }, "node_modules/get-package-type": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "license": "MIT", "engines": { "node": ">=8.0.0" @@ -5517,8 +4118,6 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -5530,8 +4129,6 @@ }, "node_modules/get-stream": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "dev": true, "license": "MIT", "dependencies": { @@ -5547,8 +4144,6 @@ }, "node_modules/get-tsconfig": { "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", "dev": true, "license": "MIT", "dependencies": { @@ -5560,19 +4155,14 @@ }, "node_modules/getopts": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", - "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==", "license": "MIT" }, "node_modules/github-from-package": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + "license": "MIT" }, "node_modules/glob": { "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { @@ -5592,8 +4182,6 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { @@ -5605,8 +4193,6 @@ }, "node_modules/globals": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", "engines": { @@ -5618,8 +4204,6 @@ }, "node_modules/globby": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "license": "MIT", "dependencies": { "array-union": "^2.1.0", @@ -5638,8 +4222,6 @@ }, "node_modules/gopd": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -5650,21 +4232,15 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, "license": "MIT" }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { @@ -5673,8 +4249,6 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -5685,8 +4259,6 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -5700,14 +4272,11 @@ }, "node_modules/has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", "optional": true }, "node_modules/hasown": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -5718,8 +4287,6 @@ }, "node_modules/he": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "license": "MIT", "bin": { @@ -5728,15 +4295,11 @@ }, "node_modules/hookable": { "version": "5.5.3", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "dev": true, "license": "MIT" }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5748,8 +4311,6 @@ }, "node_modules/html-tags": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, "license": "MIT", "engines": { @@ -5761,14 +4322,11 @@ }, "node_modules/http-cache-semantics": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause", "optional": true }, "node_modules/http-errors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", "dependencies": { "depd": "2.0.0", @@ -5783,8 +4341,6 @@ }, "node_modules/http-proxy-agent": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "license": "MIT", "dependencies": { @@ -5797,8 +4353,6 @@ }, "node_modules/https-proxy-agent": { "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { @@ -5811,8 +4365,6 @@ }, "node_modules/human-signals": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", - "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5821,8 +4373,7 @@ }, "node_modules/humanize-ms": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", "optional": true, "dependencies": { "ms": "^2.0.0" @@ -5830,8 +4381,6 @@ }, "node_modules/iconv-lite": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", - "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -5840,16 +4389,8 @@ "node": ">=0.10.0" } }, - "node_modules/idb-keyval": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", - "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==", - "license": "Apache-2.0" - }, "node_modules/ieee754": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", @@ -5863,12 +4404,11 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "license": "MIT", "engines": { "node": ">= 4" @@ -5876,8 +4416,6 @@ }, "node_modules/import-fresh": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5893,8 +4431,6 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "devOptional": true, "license": "MIT", "engines": { @@ -5903,8 +4439,7 @@ }, "node_modules/indent-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", "optional": true, "engines": { "node": ">=8" @@ -5912,15 +4447,12 @@ }, "node_modules/infer-owner": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", "optional": true }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "optional": true, "dependencies": { "once": "^1.3.0", @@ -5929,20 +4461,14 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, "node_modules/interpret": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "license": "MIT", "engines": { "node": ">= 0.10" @@ -5950,8 +4476,7 @@ }, "node_modules/ip-address": { "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", "optional": true, "dependencies": { "jsbn": "1.1.0", @@ -5963,8 +4488,6 @@ }, "node_modules/ipaddr.js": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", "engines": { "node": ">= 0.10" @@ -5972,8 +4495,6 @@ }, "node_modules/is-core-module": { "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -5987,8 +4508,6 @@ }, "node_modules/is-docker": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "license": "MIT", "bin": { @@ -6003,8 +4522,6 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6012,8 +4529,6 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "devOptional": true, "license": "MIT", "engines": { @@ -6022,8 +4537,6 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -6034,8 +4547,6 @@ }, "node_modules/is-inside-container": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "license": "MIT", "dependencies": { @@ -6053,14 +4564,11 @@ }, "node_modules/is-lambda": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", "optional": true }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -6068,8 +4576,6 @@ }, "node_modules/is-plain-obj": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, "license": "MIT", "engines": { @@ -6081,21 +4587,15 @@ }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, "license": "MIT" }, "node_modules/is-promise": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, "node_modules/is-stream": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", "dev": true, "license": "MIT", "engines": { @@ -6107,8 +4607,6 @@ }, "node_modules/is-unicode-supported": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", "engines": { @@ -6118,16 +4616,8 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "license": "MIT" - }, "node_modules/is-what": { "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", "dev": true, "license": "MIT", "engines": { @@ -6139,8 +4629,6 @@ }, "node_modules/is-wsl": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "license": "MIT", "dependencies": { @@ -6155,15 +4643,11 @@ }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "devOptional": true, "license": "ISC" }, "node_modules/jackspeak": { "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -6178,8 +4662,6 @@ }, "node_modules/jiti": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", "dev": true, "license": "MIT", "bin": { @@ -6188,8 +4670,6 @@ }, "node_modules/js-beautify": { "version": "1.15.3", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.3.tgz", - "integrity": "sha512-rKKGuyTxGNlyN4EQKWzNndzXpi0bOl8Gl8YQAW1as/oMz0XhD6sHJO1hTvoBDOSzKuJb9WkwoAb34FfdkKMv2A==", "dev": true, "license": "MIT", "dependencies": { @@ -6210,8 +4690,6 @@ }, "node_modules/js-cookie": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", "dev": true, "license": "MIT", "engines": { @@ -6220,15 +4698,11 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -6239,14 +4713,11 @@ }, "node_modules/jsbn": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT", "optional": true }, "node_modules/jsdom": { "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.0.0.tgz", - "integrity": "sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw==", "dev": true, "license": "MIT", "dependencies": { @@ -6286,8 +4757,6 @@ }, "node_modules/jsdom/node_modules/xml-name-validator": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -6296,8 +4765,6 @@ }, "node_modules/jsesc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", "bin": { @@ -6309,15 +4776,11 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", - "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", "dev": true, "license": "MIT", "engines": { @@ -6326,22 +4789,16 @@ }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", "bin": { @@ -6353,8 +4810,6 @@ }, "node_modules/jsonfile": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -6365,8 +4820,6 @@ }, "node_modules/keyv": { "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { @@ -6375,8 +4828,6 @@ }, "node_modules/knex": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz", - "integrity": "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==", "license": "MIT", "dependencies": { "colorette": "2.0.19", @@ -6426,8 +4877,6 @@ }, "node_modules/knex/node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -6443,14 +4892,10 @@ }, "node_modules/knex/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "license": "MIT" }, "node_modules/knex/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "license": "MIT", "engines": { "node": ">=8" @@ -6458,15 +4903,11 @@ }, "node_modules/kolorist": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", "dev": true, "license": "MIT" }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6479,8 +4920,6 @@ }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { @@ -6495,35 +4934,25 @@ }, "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "license": "MIT" }, "node_modules/loupe": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "dev": true, "license": "MIT" }, "node_modules/lru-cache": { "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, "license": "ISC" }, "node_modules/magic-string": { "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" @@ -6531,15 +4960,12 @@ }, "node_modules/make-error": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true, "license": "ISC" }, "node_modules/make-fetch-happen": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", "optional": true, "dependencies": { "agentkeepalive": "^4.1.3", @@ -6565,8 +4991,7 @@ }, "node_modules/make-fetch-happen/node_modules/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "optional": true, "dependencies": { "debug": "4" @@ -6577,8 +5002,7 @@ }, "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", "optional": true, "dependencies": { "@tootallnate/once": "1", @@ -6591,8 +5015,7 @@ }, "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "optional": true, "dependencies": { "agent-base": "6", @@ -6604,8 +5027,7 @@ }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -6616,8 +5038,7 @@ }, "node_modules/make-fetch-happen/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -6628,8 +5049,7 @@ }, "node_modules/make-fetch-happen/node_modules/negotiator": { "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", "optional": true, "engines": { "node": ">= 0.6" @@ -6637,14 +5057,11 @@ }, "node_modules/make-fetch-happen/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -6652,8 +5069,6 @@ }, "node_modules/media-typer": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -6661,8 +5076,6 @@ }, "node_modules/memorystream": { "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", "dev": true, "engines": { "node": ">= 0.10.0" @@ -6670,8 +5083,6 @@ }, "node_modules/merge-descriptors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", "engines": { "node": ">=18" @@ -6682,8 +5093,6 @@ }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "license": "MIT", "engines": { "node": ">= 8" @@ -6691,8 +5100,6 @@ }, "node_modules/methods": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -6700,8 +5107,6 @@ }, "node_modules/micromatch": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -6713,8 +5118,6 @@ }, "node_modules/mikro-orm": { "version": "6.4.6", - "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.4.6.tgz", - "integrity": "sha512-Lr3uFK06O/4F/AtQAsuYD6QH7DgmUooSVFVGf1y02IuiKVFKOMJ4iKimkRMyoA+ykKhgYIp8WiaEqbWJVuz4Vw==", "license": "MIT", "engines": { "node": ">= 18.12.0" @@ -6722,8 +5125,6 @@ }, "node_modules/mime-db": { "version": "1.53.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", - "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -6731,8 +5132,6 @@ }, "node_modules/mime-types": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz", - "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", "license": "MIT", "dependencies": { "mime-db": "^1.53.0" @@ -6743,8 +5142,7 @@ }, "node_modules/mimic-response": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -6754,8 +5152,6 @@ }, "node_modules/minimatch": { "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -6769,8 +5165,6 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6778,8 +5172,6 @@ }, "node_modules/minipass": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "license": "ISC", "engines": { @@ -6788,8 +5180,7 @@ }, "node_modules/minipass-collect": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -6800,8 +5191,7 @@ }, "node_modules/minipass-collect/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -6812,14 +5202,12 @@ }, "node_modules/minipass-collect/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, "node_modules/minipass-fetch": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", "optional": true, "dependencies": { "minipass": "^3.1.0", @@ -6835,8 +5223,7 @@ }, "node_modules/minipass-fetch/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -6847,14 +5234,12 @@ }, "node_modules/minipass-fetch/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, "node_modules/minipass-flush": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -6865,8 +5250,7 @@ }, "node_modules/minipass-flush/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -6877,14 +5261,12 @@ }, "node_modules/minipass-flush/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, "node_modules/minipass-pipeline": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -6895,8 +5277,7 @@ }, "node_modules/minipass-pipeline/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -6907,14 +5288,12 @@ }, "node_modules/minipass-pipeline/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, "node_modules/minipass-sized": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.0.0" @@ -6925,8 +5304,7 @@ }, "node_modules/minipass-sized/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -6937,14 +5315,12 @@ }, "node_modules/minipass-sized/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, "node_modules/minizlib": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -6955,8 +5331,7 @@ }, "node_modules/minizlib/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -6966,20 +5341,16 @@ }, "node_modules/minizlib/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/mitt": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "dev": true, "license": "MIT" }, "node_modules/mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -6989,13 +5360,10 @@ }, "node_modules/mkdirp-classic": { "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + "license": "MIT" }, "node_modules/mrmime": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, "license": "MIT", "engines": { @@ -7004,21 +5372,15 @@ }, "node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/muggle-string": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", - "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", "dev": true, "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", @@ -7035,70 +5397,23 @@ }, "node_modules/napi-build-utils": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==" + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/negotiator": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - }, "node_modules/node-abi": { "version": "3.74.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz", - "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==", + "license": "MIT", "dependencies": { "semver": "^7.3.5" }, @@ -7108,13 +5423,11 @@ }, "node_modules/node-addon-api": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" + "license": "MIT" }, "node_modules/node-gyp": { "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", "optional": true, "dependencies": { "env-paths": "^2.2.0", @@ -7137,14 +5450,12 @@ }, "node_modules/node-gyp/node_modules/abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", "optional": true }, "node_modules/node-gyp/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==", + "license": "MIT", "optional": true, "dependencies": { "balanced-match": "^1.0.0", @@ -7153,9 +5464,7 @@ }, "node_modules/node-gyp/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", + "license": "ISC", "optional": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -7174,8 +5483,7 @@ }, "node_modules/node-gyp/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "optional": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -7186,8 +5494,7 @@ }, "node_modules/node-gyp/node_modules/nopt": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", "optional": true, "dependencies": { "abbrev": "1" @@ -7201,15 +5508,11 @@ }, "node_modules/node-releases": { "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, "node_modules/nopt": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", - "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "dev": true, "license": "ISC", "dependencies": { @@ -7224,8 +5527,6 @@ }, "node_modules/npm-normalize-package-bin": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", - "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, "license": "ISC", "engines": { @@ -7234,8 +5535,6 @@ }, "node_modules/npm-run-all2": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-7.0.2.tgz", - "integrity": "sha512-7tXR+r9hzRNOPNTvXegM+QzCuMjzUIIq66VDunL6j60O4RrExx32XUhlrS7UK4VcdGw5/Wxzb3kfNcFix9JKDA==", "dev": true, "license": "MIT", "dependencies": { @@ -7261,8 +5560,6 @@ }, "node_modules/npm-run-all2/node_modules/ansi-styles": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "license": "MIT", "engines": { @@ -7274,8 +5571,6 @@ }, "node_modules/npm-run-all2/node_modules/isexe": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, "license": "ISC", "engines": { @@ -7284,8 +5579,6 @@ }, "node_modules/npm-run-all2/node_modules/which": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", - "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -7300,8 +5593,6 @@ }, "node_modules/npm-run-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "dev": true, "license": "MIT", "dependencies": { @@ -7317,8 +5608,6 @@ }, "node_modules/npm-run-path/node_modules/path-key": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, "license": "MIT", "engines": { @@ -7330,9 +5619,7 @@ }, "node_modules/npmlog": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", + "license": "ISC", "optional": true, "dependencies": { "are-we-there-yet": "^3.0.0", @@ -7346,8 +5633,6 @@ }, "node_modules/nth-check": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -7359,15 +5644,11 @@ }, "node_modules/nwsapi": { "version": "2.2.16", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", - "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", "dev": true, "license": "MIT" }, "node_modules/object-inspect": { "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -7378,8 +5659,6 @@ }, "node_modules/on-finished": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -7390,8 +5669,6 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", "dependencies": { "wrappy": "1" @@ -7399,8 +5676,6 @@ }, "node_modules/open": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "dev": true, "license": "MIT", "dependencies": { @@ -7416,19 +5691,8 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "license": "MIT", - "bin": { - "opencollective-postinstall": "index.js" - } - }, "node_modules/optionator": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { @@ -7445,8 +5709,6 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7461,8 +5723,6 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { @@ -7477,8 +5737,7 @@ }, "node_modules/p-map": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", "optional": true, "dependencies": { "aggregate-error": "^3.0.0" @@ -7492,15 +5751,11 @@ }, "node_modules/package-json-from-dist": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { @@ -7512,8 +5767,6 @@ }, "node_modules/parent-require": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", - "integrity": "sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ==", "dev": true, "engines": { "node": ">= 0.4.0" @@ -7521,8 +5774,6 @@ }, "node_modules/parse-ms": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", "dev": true, "license": "MIT", "engines": { @@ -7534,8 +5785,6 @@ }, "node_modules/parse5": { "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7547,8 +5796,6 @@ }, "node_modules/parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -7556,14 +5803,10 @@ }, "node_modules/path-browserify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "license": "MIT" }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { @@ -7572,8 +5815,7 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -7581,8 +5823,6 @@ }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { @@ -7591,14 +5831,10 @@ }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -7614,8 +5850,6 @@ }, "node_modules/path-to-regexp": { "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", "license": "MIT", "engines": { "node": ">=16" @@ -7623,8 +5857,6 @@ }, "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "license": "MIT", "engines": { "node": ">=8" @@ -7632,15 +5864,11 @@ }, "node_modules/pathe": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/pathval": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, "license": "MIT", "engines": { @@ -7649,15 +5877,11 @@ }, "node_modules/perfect-debounce": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", "dev": true, "license": "MIT" }, "node_modules/pg": { "version": "8.13.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.2.tgz", - "integrity": "sha512-L5QkPvTjVWWHbLaFjCkOSplpb2uCiRYbg0IJ2okCy5ClYfWlSgDDnvdR6dyw3EWAH2AfS4j8E61QFI7gLfTtlw==", "license": "MIT", "dependencies": { "pg-connection-string": "^2.7.0", @@ -7683,21 +5907,15 @@ }, "node_modules/pg-cloudflare": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", "license": "MIT" }, "node_modules/pg-int8": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", "license": "ISC", "engines": { "node": ">=4.0.0" @@ -7705,8 +5923,6 @@ }, "node_modules/pg-pool": { "version": "3.7.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.1.tgz", - "integrity": "sha512-xIOsFoh7Vdhojas6q3596mXFsR8nwBQBXX5JiV7p9buEVAGqYL4yFzclON5P9vFrpu1u7Zwl2oriyDa89n0wbw==", "license": "MIT", "peerDependencies": { "pg": ">=8.0" @@ -7714,14 +5930,10 @@ }, "node_modules/pg-protocol": { "version": "1.7.1", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.1.tgz", - "integrity": "sha512-gjTHWGYWsEgy9MsY0Gp6ZJxV24IjDqdpTW7Eh0x+WfJLFsm/TJx1MzL6T0D88mBvkpxotCQ6TwW6N+Kko7lhgQ==", "license": "MIT" }, "node_modules/pg-types": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", "license": "MIT", "dependencies": { "pg-int8": "1.0.1", @@ -7736,8 +5948,6 @@ }, "node_modules/pg-types/node_modules/postgres-array": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", "license": "MIT", "engines": { "node": ">=4" @@ -7745,8 +5955,6 @@ }, "node_modules/pg-types/node_modules/postgres-date": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7754,8 +5962,6 @@ }, "node_modules/pg-types/node_modules/postgres-interval": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", "license": "MIT", "dependencies": { "xtend": "^4.0.0" @@ -7766,14 +5972,10 @@ }, "node_modules/pg/node_modules/pg-connection-string": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", - "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", "license": "MIT" }, "node_modules/pgpass": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", "license": "MIT", "dependencies": { "split2": "^4.1.0" @@ -7781,14 +5983,10 @@ }, "node_modules/picocolors": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -7799,8 +5997,6 @@ }, "node_modules/pidtree": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, "license": "MIT", "bin": { @@ -7812,8 +6008,6 @@ }, "node_modules/playwright": { "version": "1.50.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", - "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7831,8 +6025,6 @@ }, "node_modules/playwright-core": { "version": "1.50.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", - "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -7842,25 +6034,8 @@ "node": ">=18" } }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/postcss": { "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -7887,8 +6062,6 @@ }, "node_modules/postcss-selector-parser": { "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "license": "MIT", "dependencies": { @@ -7901,8 +6074,6 @@ }, "node_modules/postgres-array": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", - "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", "license": "MIT", "engines": { "node": ">=12" @@ -7910,8 +6081,6 @@ }, "node_modules/postgres-bytea": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7919,8 +6088,6 @@ }, "node_modules/postgres-date": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", - "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", "license": "MIT", "engines": { "node": ">=12" @@ -7928,8 +6095,6 @@ }, "node_modules/postgres-interval": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-4.0.2.tgz", - "integrity": "sha512-EMsphSQ1YkQqKZL2cuG0zHkmjCCzQqQ71l2GXITqRwjhRleCdv00bDk/ktaSi0LnlaPzAc3535KTrjXsTdtx7A==", "license": "MIT", "engines": { "node": ">=12" @@ -7937,8 +6102,7 @@ }, "node_modules/prebuild-install": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -7962,8 +6126,6 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { @@ -7972,8 +6134,6 @@ }, "node_modules/prettier": { "version": "3.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.1.tgz", - "integrity": "sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==", "dev": true, "license": "MIT", "peer": true, @@ -7989,8 +6149,6 @@ }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "license": "MIT", "dependencies": { @@ -8002,8 +6160,6 @@ }, "node_modules/pretty-ms": { "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", - "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", "dev": true, "license": "MIT", "dependencies": { @@ -8018,14 +6174,12 @@ }, "node_modules/promise-inflight": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", "optional": true }, "node_modules/promise-retry": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", "optional": true, "dependencies": { "err-code": "^2.0.2", @@ -8037,15 +6191,11 @@ }, "node_modules/proto-list": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "dev": true, "license": "ISC" }, "node_modules/proxy-addr": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", "dependencies": { "forwarded": "0.2.0", @@ -8058,13 +6208,11 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/pump": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -8072,8 +6220,6 @@ }, "node_modules/punycode": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { @@ -8082,8 +6228,6 @@ }, "node_modules/qs": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.6" @@ -8097,8 +6241,6 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "funding": [ { "type": "github", @@ -8117,8 +6259,6 @@ }, "node_modules/range-parser": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -8126,8 +6266,6 @@ }, "node_modules/raw-body": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -8141,8 +6279,6 @@ }, "node_modules/raw-body/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -8153,8 +6289,7 @@ }, "node_modules/rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -8167,16 +6302,13 @@ }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/read-package-json-fast": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", - "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", "dev": true, "license": "ISC", "dependencies": { @@ -8189,8 +6321,7 @@ }, "node_modules/readable-stream": { "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -8202,8 +6333,6 @@ }, "node_modules/rechoir": { "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "license": "MIT", "dependencies": { "resolve": "^1.20.0" @@ -8214,20 +6343,10 @@ }, "node_modules/reflect-metadata": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "license": "Apache-2.0" }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "license": "MIT" - }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", "engines": { @@ -8236,8 +6355,6 @@ }, "node_modules/resolve": { "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -8256,8 +6373,6 @@ }, "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { @@ -8266,8 +6381,6 @@ }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, "license": "MIT", "funding": { @@ -8276,8 +6389,7 @@ }, "node_modules/retry": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", "optional": true, "engines": { "node": ">= 4" @@ -8285,8 +6397,6 @@ }, "node_modules/reusify": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -8295,16 +6405,12 @@ }, "node_modules/rfdc": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, "license": "MIT" }, "node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", "optional": true, "dependencies": { "glob": "^7.1.3" @@ -8318,8 +6424,7 @@ }, "node_modules/rimraf/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==", + "license": "MIT", "optional": true, "dependencies": { "balanced-match": "^1.0.0", @@ -8328,9 +6433,7 @@ }, "node_modules/rimraf/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", + "license": "ISC", "optional": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -8349,8 +6452,7 @@ }, "node_modules/rimraf/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "optional": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -8361,8 +6463,6 @@ }, "node_modules/rollup": { "version": "4.34.8", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", - "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8400,8 +6500,6 @@ }, "node_modules/router": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.1.0.tgz", - "integrity": "sha512-/m/NSLxeYEgWNtyC+WtNHCF7jbGxOibVWKnn+1Psff4dJGOfoXP+MuC/f2CwSmyiHdOIzYnYFp4W6GxWfekaLA==", "license": "MIT", "dependencies": { "is-promise": "^4.0.0", @@ -8414,15 +6512,11 @@ }, "node_modules/rrweb-cssom": { "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", "dev": true, "license": "MIT" }, "node_modules/run-applescript": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", "dev": true, "license": "MIT", "engines": { @@ -8434,8 +6528,6 @@ }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "funding": [ { "type": "github", @@ -8457,8 +6549,6 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -8477,14 +6567,10 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, "node_modules/saxes": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, "license": "ISC", "dependencies": { @@ -8496,8 +6582,6 @@ }, "node_modules/semver": { "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8508,8 +6592,6 @@ }, "node_modules/send": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.1.0.tgz", - "integrity": "sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==", "license": "MIT", "dependencies": { "debug": "^4.3.5", @@ -8531,8 +6613,6 @@ }, "node_modules/send/node_modules/fresh": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -8540,8 +6620,6 @@ }, "node_modules/send/node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -8549,8 +6627,6 @@ }, "node_modules/send/node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -8561,8 +6637,6 @@ }, "node_modules/serve-static": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.1.0.tgz", - "integrity": "sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA==", "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", @@ -8576,20 +6650,15 @@ }, "node_modules/set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC", "optional": true }, "node_modules/setprototypeof": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { @@ -8601,8 +6670,6 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { @@ -8611,8 +6678,6 @@ }, "node_modules/shell-quote": { "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, "license": "MIT", "engines": { @@ -8624,8 +6689,6 @@ }, "node_modules/side-channel": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -8643,8 +6706,6 @@ }, "node_modules/side-channel-list": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -8659,8 +6720,6 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -8677,8 +6736,6 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -8696,15 +6753,11 @@ }, "node_modules/siginfo": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/signal-exit": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", "engines": { @@ -8716,27 +6769,6 @@ }, "node_modules/simple-concat": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "funding": [ { "type": "github", @@ -8751,6 +6783,25 @@ "url": "https://feross.org/support" } ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", @@ -8759,8 +6810,6 @@ }, "node_modules/sirv": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", - "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", "dev": true, "license": "MIT", "dependencies": { @@ -8774,8 +6823,6 @@ }, "node_modules/slash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "license": "MIT", "engines": { "node": ">=8" @@ -8783,8 +6830,7 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", "optional": true, "engines": { "node": ">= 6.0.0", @@ -8793,8 +6839,7 @@ }, "node_modules/socks": { "version": "2.8.4", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", - "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "license": "MIT", "optional": true, "dependencies": { "ip-address": "^9.0.5", @@ -8807,8 +6852,7 @@ }, "node_modules/socks-proxy-agent": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", "optional": true, "dependencies": { "agent-base": "^6.0.2", @@ -8821,8 +6865,7 @@ }, "node_modules/socks-proxy-agent/node_modules/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "optional": true, "dependencies": { "debug": "4" @@ -8833,8 +6876,6 @@ }, "node_modules/source-map-js": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -8842,8 +6883,6 @@ }, "node_modules/speakingurl": { "version": "14.0.1", - "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", - "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -8852,8 +6891,6 @@ }, "node_modules/split2": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "license": "ISC", "engines": { "node": ">= 10.x" @@ -8861,15 +6898,13 @@ }, "node_modules/sprintf-js": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", "optional": true }, "node_modules/sqlite3": { "version": "5.1.7", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", - "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^7.0.0", @@ -8890,8 +6925,6 @@ }, "node_modules/sqlstring": { "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -8899,16 +6932,14 @@ }, "node_modules/sqlstring-sqlite": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sqlstring-sqlite/-/sqlstring-sqlite-0.1.1.tgz", - "integrity": "sha512-9CAYUJ0lEUPYJrswqiqdINNSfq3jqWo/bFJ7tufdoNeSK0Fy+d1kFTxjqO9PIqza0Kri+ZtYMfPVf1aZaFOvrQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/ssri": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", "optional": true, "dependencies": { "minipass": "^3.1.1" @@ -8919,8 +6950,7 @@ }, "node_modules/ssri/node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", "optional": true, "dependencies": { "yallist": "^4.0.0" @@ -8931,21 +6961,16 @@ }, "node_modules/ssri/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "optional": true }, "node_modules/stackback": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -8953,23 +6978,35 @@ }, "node_modules/std-env": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", - "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", "dev": true, "license": "MIT" }, "node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -8981,26 +7018,47 @@ "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -9010,24 +7068,16 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { "node": ">=8" } }, "node_modules/strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", "engines": { @@ -9036,8 +7086,6 @@ }, "node_modules/strip-final-newline": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", "dev": true, "license": "MIT", "engines": { @@ -9049,8 +7097,6 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { @@ -9062,8 +7108,6 @@ }, "node_modules/superjson": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", - "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9075,8 +7119,6 @@ }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -9088,8 +7130,6 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -9100,21 +7140,15 @@ }, "node_modules/svg-tags": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, "node_modules/symbol-tree": { "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true, "license": "MIT" }, "node_modules/synckit": { "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, "license": "MIT", "dependencies": { @@ -9130,8 +7164,7 @@ }, "node_modules/tar": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -9146,8 +7179,7 @@ }, "node_modules/tar-fs": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "license": "MIT", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -9157,13 +7189,11 @@ }, "node_modules/tar-fs/node_modules/chownr": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "license": "ISC" }, "node_modules/tar-stream": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -9177,54 +7207,24 @@ }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", "engines": { "node": ">=8" } }, "node_modules/tar/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/tarn": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", - "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", "license": "MIT", "engines": { "node": ">=8.0.0" } }, - "node_modules/tesseract.js": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-6.0.0.tgz", - "integrity": "sha512-tqYCod1HwJzkeZw1l6XWx+ly2hhisGcBtak9MArhYwDAxL0NgeVhLJcUjqPxZMQtpgtVUzWcpZPryi+hnaQGVw==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "bmp-js": "^0.1.0", - "idb-keyval": "^6.2.0", - "is-url": "^1.2.4", - "node-fetch": "^2.6.9", - "opencollective-postinstall": "^2.0.3", - "regenerator-runtime": "^0.13.3", - "tesseract.js-core": "^6.0.0", - "wasm-feature-detect": "^1.2.11", - "zlibjs": "^0.3.1" - } - }, - "node_modules/tesseract.js-core": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.0.0.tgz", - "integrity": "sha512-1Qncm/9oKM7xgrQXZXNB+NRh19qiXGhxlrR8EwFbK5SaUbPZnS5OMtP/ghtqfd23hsr1ZvZbZjeuAGcMxd/ooA==", - "license": "Apache-2.0" - }, "node_modules/tildify": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", - "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", "license": "MIT", "engines": { "node": ">=8" @@ -9232,22 +7232,16 @@ }, "node_modules/tinybench": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, "license": "MIT" }, "node_modules/tinypool": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", "dev": true, "license": "MIT", "engines": { @@ -9256,8 +7250,6 @@ }, "node_modules/tinyrainbow": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", "engines": { @@ -9266,8 +7258,6 @@ }, "node_modules/tinyspy": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", "dev": true, "license": "MIT", "engines": { @@ -9275,29 +7265,23 @@ } }, "node_modules/tldts": { - "version": "6.1.78", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.78.tgz", - "integrity": "sha512-fSgYrW0ITH0SR/CqKMXIruYIPpNu5aDgUp22UhYoSrnUQwc7SBqifEBFNce7AAcygUPBo6a/gbtcguWdmko4RQ==", + "version": "6.1.77", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.78" + "tldts-core": "^6.1.77" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.78", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.78.tgz", - "integrity": "sha512-jS0svNsB99jR6AJBmfmEWuKIgz91Haya91Z43PATaeHJ24BkMoNRb/jlaD37VYjb0mYf6gRL/HOnvS1zEnYBiw==", + "version": "6.1.77", "dev": true, "license": "MIT" }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -9308,8 +7292,6 @@ }, "node_modules/toidentifier": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", "engines": { "node": ">=0.6" @@ -9317,8 +7299,6 @@ }, "node_modules/totalist": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "license": "MIT", "engines": { @@ -9327,8 +7307,6 @@ }, "node_modules/tough-cookie": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.1.tgz", - "integrity": "sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9340,8 +7318,6 @@ }, "node_modules/tr46": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, "license": "MIT", "dependencies": { @@ -9353,8 +7329,6 @@ }, "node_modules/ts-api-utils": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, "license": "MIT", "engines": { @@ -9366,8 +7340,6 @@ }, "node_modules/ts-morph": { "version": "25.0.1", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-25.0.1.tgz", - "integrity": "sha512-QJEiTdnz1YjrB3JFhd626gX4rKHDLSjSVMvGGG4v7ONc3RBwa0Eei98G9AT9uNFDMtV54JyuXsFeC+OH0n6bXQ==", "license": "MIT", "dependencies": { "@ts-morph/common": "~0.26.0", @@ -9376,8 +7348,6 @@ }, "node_modules/ts-node": { "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9420,8 +7390,6 @@ }, "node_modules/tsconfig-paths": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "license": "MIT", "dependencies": { @@ -9435,15 +7403,11 @@ }, "node_modules/tslib": { "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, "node_modules/tsx": { "version": "4.19.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", - "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9460,26 +7424,9 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsx/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -9489,8 +7436,6 @@ }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { @@ -9502,8 +7447,6 @@ }, "node_modules/type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -9515,8 +7458,6 @@ }, "node_modules/type-is": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.0.tgz", - "integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==", "license": "MIT", "dependencies": { "content-type": "^1.0.5", @@ -9529,8 +7470,6 @@ }, "node_modules/typescript": { "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -9543,8 +7482,6 @@ }, "node_modules/typescript-eslint": { "version": "8.24.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.24.1.tgz", - "integrity": "sha512-cw3rEdzDqBs70TIcb0Gdzbt6h11BSs2pS0yaq7hDWDBtCCSei1pPSUXE9qUdQ/Wm9NgFg8mKtMt1b8fTHIl1jA==", "dev": true, "license": "MIT", "dependencies": { @@ -9566,15 +7503,11 @@ }, "node_modules/undici-types": { "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true, "license": "MIT" }, "node_modules/unicorn-magic": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "dev": true, "license": "MIT", "engines": { @@ -9586,8 +7519,7 @@ }, "node_modules/unique-filename": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", "optional": true, "dependencies": { "unique-slug": "^2.0.0" @@ -9595,8 +7527,7 @@ }, "node_modules/unique-slug": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", "optional": true, "dependencies": { "imurmurhash": "^0.1.4" @@ -9604,8 +7535,6 @@ }, "node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "license": "MIT", "engines": { "node": ">= 10.0.0" @@ -9613,8 +7542,6 @@ }, "node_modules/unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -9622,8 +7549,6 @@ }, "node_modules/update-browserslist-db": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "dev": true, "funding": [ { @@ -9653,8 +7578,6 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -9663,14 +7586,10 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -9690,15 +7609,11 @@ }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true, "license": "MIT" }, "node_modules/vary": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -9706,8 +7621,6 @@ }, "node_modules/vite": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz", - "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==", "dev": true, "license": "MIT", "dependencies": { @@ -9778,8 +7691,6 @@ }, "node_modules/vite-hot-client": { "version": "0.2.4", - "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-0.2.4.tgz", - "integrity": "sha512-a1nzURqO7DDmnXqabFOliz908FRmIppkBKsJthS8rbe8hBEXwEwe4C3Pp33Z1JoFCYfVL4kTOMLKk0ZZxREIeA==", "dev": true, "license": "MIT", "funding": { @@ -9791,8 +7702,6 @@ }, "node_modules/vite-node": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.6.tgz", - "integrity": "sha512-s51RzrTkXKJrhNbUzQRsarjmAae7VmMPAsRT7lppVpIg6mK3zGthP9Hgz0YQQKuNcF+Ii7DfYk3Fxz40jRmePw==", "dev": true, "license": "MIT", "dependencies": { @@ -9814,8 +7723,6 @@ }, "node_modules/vite-plugin-inspect": { "version": "0.8.9", - "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-0.8.9.tgz", - "integrity": "sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==", "dev": true, "license": "MIT", "dependencies": { @@ -9846,8 +7753,6 @@ }, "node_modules/vite-plugin-vue-devtools": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.7.2.tgz", - "integrity": "sha512-5V0UijQWiSBj32blkyPEqIbzc6HO9c1bwnBhx+ay2dzU0FakH+qMdNUT8nF9BvDE+i6I1U8CqCuJiO20vKEdQw==", "dev": true, "license": "MIT", "dependencies": { @@ -9868,8 +7773,6 @@ }, "node_modules/vite-plugin-vue-inspector": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.1.tgz", - "integrity": "sha512-cBk172kZKTdvGpJuzCCLg8lJ909wopwsu3Ve9FsL1XsnLBiRT9U3MePcqrgGHgCX2ZgkqZmAGR8taxw+TV6s7A==", "dev": true, "license": "MIT", "dependencies": { @@ -9887,282 +7790,8 @@ "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0" } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/vite/node_modules/@esbuild/linux-x64": { "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", "cpu": [ "x64" ], @@ -10176,146 +7805,8 @@ "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/vite/node_modules/esbuild": { "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -10355,8 +7846,6 @@ }, "node_modules/vitest": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.6.tgz", - "integrity": "sha512-/iL1Sc5VeDZKPDe58oGK4HUFLhw6b5XdY1MYawjuSaDA4sEfYlY9HnS6aCEG26fX+MgUi7MwlduTBHHAI/OvMA==", "dev": true, "license": "MIT", "dependencies": { @@ -10425,15 +7914,11 @@ }, "node_modules/vscode-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", - "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "dev": true, "license": "MIT" }, "node_modules/vue": { "version": "3.5.13", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", - "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", "license": "MIT", "dependencies": { "@vue/compiler-dom": "3.5.13", @@ -10453,15 +7938,11 @@ }, "node_modules/vue-component-type-helpers": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.2.2.tgz", - "integrity": "sha512-6lLY+n2xz2kCYshl59mL6gy8OUUTmkscmDFMO8i7Lj+QKwgnIFUZmM1i/iTYObtrczZVdw7UakPqDTGwVSGaRg==", "dev": true, "license": "MIT" }, "node_modules/vue-eslint-parser": { "version": "9.4.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", - "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", "dev": true, "license": "MIT", "dependencies": { @@ -10485,8 +7966,6 @@ }, "node_modules/vue-eslint-parser/node_modules/eslint-scope": { "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10502,8 +7981,6 @@ }, "node_modules/vue-eslint-parser/node_modules/espree": { "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10522,7 +7999,6 @@ "version": "10.0.5", "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-10.0.5.tgz", "integrity": "sha512-9/gmDlCblz3i8ypu/afiIc/SUIfTTE1mr0mZhb9pk70xo2csHAM9mp2gdQ3KD2O0AM3Hz/5ypb+FycTj/lHlPQ==", - "license": "MIT", "dependencies": { "@intlify/core-base": "10.0.5", "@intlify/shared": "10.0.5", @@ -10540,8 +8016,6 @@ }, "node_modules/vue-router": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.0.tgz", - "integrity": "sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==", "license": "MIT", "dependencies": { "@vue/devtools-api": "^6.6.4" @@ -10555,8 +8029,6 @@ }, "node_modules/vue-tsc": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.2.tgz", - "integrity": "sha512-1icPKkxAA5KTAaSwg0wVWdE48EdsH8fgvcbAiqojP4jXKl6LEM3soiW1aG/zrWrFt8Mw1ncG2vG1PvpZpVfehA==", "dev": true, "license": "MIT", "dependencies": { @@ -10571,9 +8043,7 @@ } }, "node_modules/vuetify": { - "version": "3.7.13", - "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.7.13.tgz", - "integrity": "sha512-4+RuQU+zLtXhlN2eZUpKXums9ftzUzhMeiNEJvvJY4XdOzVwUCth2dTnEZkSF6EKdLHk3WhtRk0cIWXZxpBvcw==", + "version": "3.7.12", "license": "MIT", "engines": { "node": "^12.20 || >=14.13" @@ -10602,8 +8072,6 @@ }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "license": "MIT", "dependencies": { @@ -10615,24 +8083,14 @@ }, "node_modules/w3c-xmlserializer/node_modules/xml-name-validator": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18" } }, - "node_modules/wasm-feature-detect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", - "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", - "license": "Apache-2.0" - }, "node_modules/webidl-conversions": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -10641,8 +8099,6 @@ }, "node_modules/whatwg-encoding": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10654,8 +8110,6 @@ }, "node_modules/whatwg-encoding/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { @@ -10667,8 +8121,6 @@ }, "node_modules/whatwg-mimetype": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, "license": "MIT", "engines": { @@ -10677,8 +8129,6 @@ }, "node_modules/whatwg-url": { "version": "14.1.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.1.tgz", - "integrity": "sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10691,8 +8141,6 @@ }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "devOptional": true, "license": "ISC", "dependencies": { @@ -10707,8 +8155,6 @@ }, "node_modules/why-is-node-running": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { @@ -10724,8 +8170,7 @@ }, "node_modules/wide-align": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", "optional": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" @@ -10733,8 +8178,7 @@ }, "node_modules/wide-align/node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "optional": true, "engines": { "node": ">=8" @@ -10742,14 +8186,12 @@ }, "node_modules/wide-align/node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", "optional": true }, "node_modules/wide-align/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "optional": true, "dependencies": { "emoji-regex": "^8.0.0", @@ -10762,8 +8204,7 @@ }, "node_modules/wide-align/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "optional": true, "dependencies": { "ansi-regex": "^5.0.1" @@ -10774,8 +8215,6 @@ }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { @@ -10783,18 +8222,16 @@ } }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "8.1.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -10803,8 +8240,6 @@ "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { @@ -10819,16 +8254,60 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, "node_modules/ws": { "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "license": "MIT", "engines": { @@ -10849,8 +8328,6 @@ }, "node_modules/xml-name-validator": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -10859,15 +8336,11 @@ }, "node_modules/xmlchars": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true, "license": "MIT" }, "node_modules/xtend": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "license": "MIT", "engines": { "node": ">=0.4" @@ -10875,8 +8348,6 @@ }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "license": "ISC", "engines": { @@ -10885,15 +8356,11 @@ }, "node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "dependencies": { @@ -10911,18 +8378,51 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", "engines": { "node": ">=12" } }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, "license": "MIT", "engines": { @@ -10931,8 +8431,6 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { @@ -10944,8 +8442,6 @@ }, "node_modules/yoctocolors": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", - "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", "dev": true, "license": "MIT", "engines": { @@ -10954,15 +8450,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zlibjs": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz", - "integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==", - "license": "MIT", - "engines": { - "node": "*" - } } } } From ceef74f1afc8d766f6346874d23c3838dccef5bf Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 4 Mar 2025 15:50:20 +0100 Subject: [PATCH 02/49] feat: controller en service laag toegevoegd voor student/:id/classes --- backend/src/controllers/students.ts | 53 ++++++++++++++++++-- backend/src/data/classes/class-repository.ts | 7 +++ backend/src/interfaces/classes.ts | 17 +++++++ backend/src/routes/class.ts | 2 +- backend/src/routes/student.ts | 20 ++------ backend/src/services/students.ts | 51 ++++++++++++++++++- 6 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 backend/src/interfaces/classes.ts diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index b129eb57..9b4b8f3c 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,13 +1,31 @@ import { Request, Response } from 'express'; -import { getStudentById } from "../services/students"; +import { getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; +import { ClassDTO } from '../interfaces/classes'; -export async function getStudent( +export async function getAllStudentsHandler ( + req: Request, + res: Response, +): Promise { + try { + res.json({ + students: [ + '0', + '1', + ] + }); + } catch (error) { + console.error('Error fetching learning objects:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +export async function getStudentHandler( req: Request, res: Response, ): Promise { try { const username = req.params.id; - const student = await getStudentById(username); + const student = await getStudent(username); if (!student) { res.status(404).json({ error: "Student not found" }); @@ -21,7 +39,34 @@ export async function getStudent( } res.json(student); } - + + } catch (error) { + console.error('Error fetching learning objects:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +export async function getStudentClassesHandler ( + req: Request, + res: Response, +): Promise { + try { + const full = req.query.full === 'true'; + const username = req.params.id; + + let classes: ClassDTO[] | string[]; + if (full) classes = await getStudentClasses(username); + else classes = await getStudentClassIds(username); + + res.json({ + classes: classes, + endpoints: { + self: `${req.baseUrl}/${req.params.id}`, + classes: `${req.baseUrl}/${req.params.id}/invitations`, + questions: `${req.baseUrl}/${req.params.id}/assignments`, + students: `${req.baseUrl}/${req.params.id}/students`, + } + }); } catch (error) { console.error('Error fetching learning objects:', error); res.status(500).json({ error: 'Internal server error' }); diff --git a/backend/src/data/classes/class-repository.ts b/backend/src/data/classes/class-repository.ts index e3b9f959..a9455323 100644 --- a/backend/src/data/classes/class-repository.ts +++ b/backend/src/data/classes/class-repository.ts @@ -1,5 +1,6 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Class } from '../../entities/classes/class.entity.js'; +import { Student } from '../../entities/users/student.entity.js'; export class ClassRepository extends DwengoEntityRepository { public findById(id: string): Promise { @@ -8,4 +9,10 @@ export class ClassRepository extends DwengoEntityRepository { public deleteById(id: string): Promise { return this.deleteWhere({ classId: id }); } + public findByStudent(student: Student): Promise { + return this.find( + { students: student }, + { populate: ["students", "teachers"] } // voegt student en teacher objecten toe + ) + } } diff --git a/backend/src/interfaces/classes.ts b/backend/src/interfaces/classes.ts new file mode 100644 index 00000000..78731b59 --- /dev/null +++ b/backend/src/interfaces/classes.ts @@ -0,0 +1,17 @@ +import { ClassJoinRequest } from "../entities/classes/class-join-request.entity"; +import { Student } from "../entities/users/student.entity"; +import { Teacher } from "../entities/users/teacher.entity"; + +export interface ClassDTO { + id: string; + displayName: string; + teachers: string[]; + students: string[]; + joinRequests: string[]; + endpoints?: { + classes: string; + questions: string; + invitations: string; + groups: string; + }; +} diff --git a/backend/src/routes/class.ts b/backend/src/routes/class.ts index e554a7f2..f310367d 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/class.ts @@ -19,7 +19,7 @@ router.get('/:id', (req, res) => { teachers: [ '0' ], students: [ '0' ], joinRequests: [ '0' ], - links: { + endpoints: { self: `${req.baseUrl}/${req.params.id}`, classes: `${req.baseUrl}/${req.params.id}/invitations`, questions: `${req.baseUrl}/${req.params.id}/assignments`, diff --git a/backend/src/routes/student.ts b/backend/src/routes/student.ts index 6a6280e6..ca74d2f7 100644 --- a/backend/src/routes/student.ts +++ b/backend/src/routes/student.ts @@ -1,27 +1,15 @@ import express from 'express' -import { getStudentById } from '../services/students'; -import { getStudent } from '../controllers/students'; +import { getAllStudentsHandler, getStudentClassesHandler, getStudentHandler } from '../controllers/students'; const router = express.Router(); // root endpoint used to search objects -router.get('/', (req, res) => { - res.json({ - students: [ - '0', - '1', - ] - }); -}); +router.get('/', getAllStudentsHandler); // information about a student's profile -router.get('/:id', getStudent); +router.get('/:id', getStudentHandler); // the list of classes a student is in -router.get('/:id/classes', (req, res) => { - res.json({ - classes: [ '0' ], - }); -}) +router.get('/:id/classes', getStudentClassesHandler); // the list of submissions a student has made router.get('/:id/submissions', (req, res) => { diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index b2aa953b..d38103ed 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,7 +1,14 @@ -import { getStudentRepository } from "../data/repositories"; +import { getClassRepository, getStudentRepository } from "../data/repositories"; +import { Class } from "../entities/classes/class.entity"; +import { ClassDTO } from "../interfaces/classes"; import { StudentDTO } from "../interfaces/students"; -export async function getStudentById(username: string): Promise { +export async function getAllStudents(): Promise { + // TODO + return []; +} + +export async function getStudent(username: string): Promise { const studentRepository = getStudentRepository(); const student = await studentRepository.findByUsername(username); @@ -16,3 +23,43 @@ export async function getStudentById(username: string): Promise { + const studentRepository = getStudentRepository(); + const student = await studentRepository.findByUsername(username); + + if (!student) return []; + + const classRepository = getClassRepository(); + // a weird error when running npm run dev occurs when using .findByStudent + // the error says that the function could not be found which is weird + // because typescript does not throw any errors + const classes = await classRepository.find( + { students: student }, + { populate: ["students", "teachers"] } // voegt student en teacher objecten toe + ) + // const classes = await classRepository.findByStudent(student); + + if (!classes) return []; + + return classes; +} + +export async function getStudentClasses(username: string): Promise { + const classes = await fetchStudentClasses(username); + + return classes.map((cls: Class): ClassDTO => { + return { + id: cls.classId, + displayName: cls.displayName, + teachers: cls.teachers.map(teacher => teacher.username), + students: cls.students.map(student => student.username), + joinRequests: [], // TODO + } + }); +} + +export async function getStudentClassIds(username: string): Promise { + const classes = await fetchStudentClasses(username); + return classes.map(cls => cls.classId); // class is a native keyword +} + From e9d9e52f9d3fba770e40b89c62b77ca28e35fc02 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 4 Mar 2025 16:32:59 +0100 Subject: [PATCH 03/49] feat: class/:id service en controller laag geimplementeerd (BEVAT NOG BUG) --- backend/src/controllers/classes.ts | 29 +++++++++++++++++++++++++++++ backend/src/interfaces/classes.ts | 20 ++++++++++++++------ backend/src/routes/class.ts | 17 ++--------------- backend/src/services/class.ts | 12 ++++++++++++ backend/src/services/students.ts | 15 +++------------ 5 files changed, 60 insertions(+), 33 deletions(-) create mode 100644 backend/src/controllers/classes.ts create mode 100644 backend/src/services/class.ts diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts new file mode 100644 index 00000000..f4c8666d --- /dev/null +++ b/backend/src/controllers/classes.ts @@ -0,0 +1,29 @@ +import { Request, Response } from 'express'; +import { getClass } from '../services/class'; + +export async function getClassHandler( + req: Request, + res: Response, +): Promise { + try { + const classId = req.params.id; + const cls = await getClass(classId); + + if (!cls) { + res.status(404).json({ error: "Student not found" }); + return; + } else { + cls.endpoints = { + self: `${req.baseUrl}/${req.params.id}`, + invitations: `${req.baseUrl}/${req.params.id}/invitations`, + assignments: `${req.baseUrl}/${req.params.id}/assignments`, + students: `${req.baseUrl}/${req.params.id}/students`, + } + + res.json(cls); + } + } catch (error) { + console.error('Error fetching learning objects:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} \ No newline at end of file diff --git a/backend/src/interfaces/classes.ts b/backend/src/interfaces/classes.ts index 78731b59..5c285446 100644 --- a/backend/src/interfaces/classes.ts +++ b/backend/src/interfaces/classes.ts @@ -1,6 +1,4 @@ -import { ClassJoinRequest } from "../entities/classes/class-join-request.entity"; -import { Student } from "../entities/users/student.entity"; -import { Teacher } from "../entities/users/teacher.entity"; +import { Class } from "../entities/classes/class.entity"; export interface ClassDTO { id: string; @@ -9,9 +7,19 @@ export interface ClassDTO { students: string[]; joinRequests: string[]; endpoints?: { - classes: string; - questions: string; + self: string; invitations: string; - groups: string; + assignments: string; + students: string; }; } + +export function mapToClassDTO(cls: Class): ClassDTO { + return { + id: cls.classId, + displayName: cls.displayName, + teachers: cls.teachers.map(teacher => teacher.username), + students: cls.students.map(student => student.username), + joinRequests: [], // TODO + } +}; diff --git a/backend/src/routes/class.ts b/backend/src/routes/class.ts index f310367d..65ca9362 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/class.ts @@ -1,4 +1,5 @@ import express from 'express' +import { getClassHandler } from '../controllers/classes'; const router = express.Router(); // root endpoint used to search objects @@ -12,21 +13,7 @@ router.get('/', (req, res) => { }); // information about an class with id 'id' -router.get('/:id', (req, res) => { - res.json({ - id: req.params.id, - displayName: 'Klas 4B', - teachers: [ '0' ], - students: [ '0' ], - joinRequests: [ '0' ], - endpoints: { - self: `${req.baseUrl}/${req.params.id}`, - classes: `${req.baseUrl}/${req.params.id}/invitations`, - questions: `${req.baseUrl}/${req.params.id}/assignments`, - students: `${req.baseUrl}/${req.params.id}/students`, - } - }); -}) +router.get('/:id', getClassHandler); router.get('/:id/invitations', (req, res) => { res.json({ diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts new file mode 100644 index 00000000..3a3e8322 --- /dev/null +++ b/backend/src/services/class.ts @@ -0,0 +1,12 @@ +import { getClassRepository } from "../data/repositories"; +import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; + +export async function getClass(classId: string): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classId); + + if (!cls) return null; + else { + return mapToClassDTO(cls); + } +} \ No newline at end of file diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index d38103ed..4bfd7673 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,6 +1,6 @@ import { getClassRepository, getStudentRepository } from "../data/repositories"; import { Class } from "../entities/classes/class.entity"; -import { ClassDTO } from "../interfaces/classes"; +import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; import { StudentDTO } from "../interfaces/students"; export async function getAllStudents(): Promise { @@ -46,20 +46,11 @@ async function fetchStudentClasses(username: string): Promise { export async function getStudentClasses(username: string): Promise { const classes = await fetchStudentClasses(username); - - return classes.map((cls: Class): ClassDTO => { - return { - id: cls.classId, - displayName: cls.displayName, - teachers: cls.teachers.map(teacher => teacher.username), - students: cls.students.map(student => student.username), - joinRequests: [], // TODO - } - }); + return classes.map(mapToClassDTO); } export async function getStudentClassIds(username: string): Promise { const classes = await fetchStudentClasses(username); - return classes.map(cls => cls.classId); // class is a native keyword + return classes.map(cls => cls.classId); // 'class' is a native keyword } From 7a8673f66e51bda21e79026fc211bbfb82b904ee Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 4 Mar 2025 16:43:27 +0100 Subject: [PATCH 04/49] fix: duplicate lijn in package.json --- backend/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index 29c7ecbc..4911d3f4 100644 --- a/backend/package.json +++ b/backend/package.json @@ -17,7 +17,6 @@ "@mikro-orm/core": "^6.4.6", "@mikro-orm/postgresql": "^6.4.6", "@mikro-orm/reflection": "^6.4.6", - "@types/js-yaml": "^4.0.9", "axios": "^1.8.1", "@mikro-orm/sqlite": "6.4.6", "dotenv": "^16.4.7", From 55387066f093589fbbe98fa516c177e2e726c8ca Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Wed, 5 Mar 2025 15:48:35 +0100 Subject: [PATCH 05/49] fix: @entity(...) decorator gefixt in backend/src/entities --- backend/src/entities/assignments/assignment.entity.ts | 3 ++- backend/src/entities/assignments/group.entity.ts | 3 ++- backend/src/entities/assignments/submission.entity.ts | 3 ++- backend/src/entities/classes/class-join-request.entity.ts | 3 ++- backend/src/entities/classes/class.entity.ts | 3 ++- backend/src/entities/classes/teacher-invitation.entity.ts | 3 ++- backend/src/entities/content/attachment.entity.ts | 3 ++- backend/src/entities/content/learning-object.entity.ts | 3 ++- backend/src/entities/content/learning-path.entity.ts | 3 ++- backend/src/entities/questions/answer.entity.ts | 3 ++- backend/src/entities/questions/question.entity.ts | 3 ++- backend/src/entities/users/teacher.entity.ts | 3 ++- 12 files changed, 24 insertions(+), 12 deletions(-) diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index e883632b..785a8b9c 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -9,8 +9,9 @@ import { import { Class } from '../classes/class.entity.js'; import { Group } from './group.entity.js'; import { Language } from '../content/language.js'; +import { AssignmentRepository } from '../../data/assignments/assignment-repository.js'; -@Entity() +@Entity({ repository: () => AssignmentRepository }) export class Assignment { @ManyToOne({ entity: () => Class, primary: true }) within!: Class; diff --git a/backend/src/entities/assignments/group.entity.ts b/backend/src/entities/assignments/group.entity.ts index 80da7d8b..cb4cd6e6 100644 --- a/backend/src/entities/assignments/group.entity.ts +++ b/backend/src/entities/assignments/group.entity.ts @@ -1,8 +1,9 @@ import { Entity, ManyToMany, ManyToOne, PrimaryKey } from '@mikro-orm/core'; import { Assignment } from './assignment.entity.js'; import { Student } from '../users/student.entity.js'; +import { GroupRepository } from '../../data/assignments/group-repository.js'; -@Entity() +@Entity({ repository: () => GroupRepository }) export class Group { @ManyToOne({ entity: () => Assignment, primary: true }) assignment!: Assignment; diff --git a/backend/src/entities/assignments/submission.entity.ts b/backend/src/entities/assignments/submission.entity.ts index 02cbeeae..26269020 100644 --- a/backend/src/entities/assignments/submission.entity.ts +++ b/backend/src/entities/assignments/submission.entity.ts @@ -2,8 +2,9 @@ import { Student } from '../users/student.entity.js'; import { Group } from './group.entity.js'; import { Entity, Enum, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { Language } from '../content/language.js'; +import { SubmissionRepository } from '../../data/assignments/submission-repository.js'; -@Entity() +@Entity({ repository: () => SubmissionRepository }) export class Submission { @PrimaryKey({ type: 'string' }) learningObjectHruid!: string; diff --git a/backend/src/entities/classes/class-join-request.entity.ts b/backend/src/entities/classes/class-join-request.entity.ts index 9a883688..0636e044 100644 --- a/backend/src/entities/classes/class-join-request.entity.ts +++ b/backend/src/entities/classes/class-join-request.entity.ts @@ -1,8 +1,9 @@ import { Entity, Enum, ManyToOne } from '@mikro-orm/core'; import { Student } from '../users/student.entity.js'; import { Class } from './class.entity.js'; +import { ClassJoinRequestRepository } from '../../data/classes/class-join-request-repository.js'; -@Entity() +@Entity({ repository: () => ClassJoinRequestRepository }) export class ClassJoinRequest { @ManyToOne({ entity: () => Student, primary: true }) requester!: Student; diff --git a/backend/src/entities/classes/class.entity.ts b/backend/src/entities/classes/class.entity.ts index 1f5835d2..06d31479 100644 --- a/backend/src/entities/classes/class.entity.ts +++ b/backend/src/entities/classes/class.entity.ts @@ -8,8 +8,9 @@ import { import { v4 } from 'uuid'; import { Teacher } from '../users/teacher.entity.js'; import { Student } from '../users/student.entity.js'; +import { ClassRepository } from '../../data/classes/class-repository.js'; -@Entity() +@Entity({ repository: () => ClassRepository }) export class Class { @PrimaryKey() classId = v4(); diff --git a/backend/src/entities/classes/teacher-invitation.entity.ts b/backend/src/entities/classes/teacher-invitation.entity.ts index 375bf719..42700d3a 100644 --- a/backend/src/entities/classes/teacher-invitation.entity.ts +++ b/backend/src/entities/classes/teacher-invitation.entity.ts @@ -1,11 +1,12 @@ import { Entity, ManyToOne } from '@mikro-orm/core'; import { Teacher } from '../users/teacher.entity.js'; import { Class } from './class.entity.js'; +import { TeacherInvitationRepository } from '../../data/classes/teacher-invitation-repository.js'; /** * Invitation of a teacher into a class (in order to teach it). */ -@Entity() +@Entity({ repository: () => TeacherInvitationRepository }) export class TeacherInvitation { @ManyToOne({ entity: () => Teacher, primary: true }) sender!: Teacher; diff --git a/backend/src/entities/content/attachment.entity.ts b/backend/src/entities/content/attachment.entity.ts index 5a77d4b7..7f14d178 100644 --- a/backend/src/entities/content/attachment.entity.ts +++ b/backend/src/entities/content/attachment.entity.ts @@ -1,7 +1,8 @@ import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { LearningObject } from './learning-object.entity.js'; +import { AttachmentRepository } from '../../data/content/attachment-repository.js'; -@Entity() +@Entity({ repository: () => AttachmentRepository }) export class Attachment { @ManyToOne({ entity: () => LearningObject, primary: true }) learningObject!: LearningObject; diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index aeee268d..179a2f5f 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -11,8 +11,9 @@ import { import { Language } from './language.js'; import { Attachment } from './attachment.entity.js'; import { Teacher } from '../users/teacher.entity.js'; +import { LearningObjectRepository } from '../../data/content/learning-object-repository.js'; -@Entity() +@Entity({ repository: () => LearningObjectRepository }) export class LearningObject { @PrimaryKey({ type: 'string' }) hruid!: string; diff --git a/backend/src/entities/content/learning-path.entity.ts b/backend/src/entities/content/learning-path.entity.ts index f426cdfe..de62aa15 100644 --- a/backend/src/entities/content/learning-path.entity.ts +++ b/backend/src/entities/content/learning-path.entity.ts @@ -10,8 +10,9 @@ import { } from '@mikro-orm/core'; import { Language } from './language.js'; import { Teacher } from '../users/teacher.entity.js'; +import { LearningPathRepository } from '../../data/content/learning-path-repository.js'; -@Entity() +@Entity({ repository: () => LearningPathRepository }) export class LearningPath { @PrimaryKey({ type: 'string' }) hruid!: string; diff --git a/backend/src/entities/questions/answer.entity.ts b/backend/src/entities/questions/answer.entity.ts index d07a78ca..7fb64575 100644 --- a/backend/src/entities/questions/answer.entity.ts +++ b/backend/src/entities/questions/answer.entity.ts @@ -1,8 +1,9 @@ import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { Question } from './question.entity.js'; import { Teacher } from '../users/teacher.entity.js'; +import { AnswerRepository } from '../../data/questions/answer-repository.js'; -@Entity() +@Entity({ repository: () => AnswerRepository }) export class Answer { @ManyToOne({ entity: () => Teacher, primary: true }) author!: Teacher; diff --git a/backend/src/entities/questions/question.entity.ts b/backend/src/entities/questions/question.entity.ts index 6c0d07e5..67efdfe7 100644 --- a/backend/src/entities/questions/question.entity.ts +++ b/backend/src/entities/questions/question.entity.ts @@ -1,8 +1,9 @@ import { Entity, Enum, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { Language } from '../content/language.js'; import { Student } from '../users/student.entity.js'; +import { QuestionRepository } from '../../data/questions/question-repository.js'; -@Entity() +@Entity({ repository: () => QuestionRepository }) export class Question { @PrimaryKey({ type: 'string' }) learningObjectHruid!: string; diff --git a/backend/src/entities/users/teacher.entity.ts b/backend/src/entities/users/teacher.entity.ts index 2327527c..d53ca603 100644 --- a/backend/src/entities/users/teacher.entity.ts +++ b/backend/src/entities/users/teacher.entity.ts @@ -1,8 +1,9 @@ import { Collection, Entity, ManyToMany } from '@mikro-orm/core'; import { User } from './user.entity.js'; import { Class } from '../classes/class.entity.js'; +import { TeacherRepository } from '../../data/users/teacher-repository.js'; -@Entity() +@Entity({ repository: () => TeacherRepository }) export class Teacher extends User { @ManyToMany(() => Class) classes!: Collection; From 123fdf0fa11b0311399f50f0fbc7c64c9b91b318 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Wed, 5 Mar 2025 15:57:29 +0100 Subject: [PATCH 06/49] fix: code teruggezet die veroorzaakt werd door bug in backend/src/entities --- backend/src/services/students.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 4bfd7673..3a1b601f 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -30,14 +30,7 @@ async function fetchStudentClasses(username: string): Promise { if (!student) return []; const classRepository = getClassRepository(); - // a weird error when running npm run dev occurs when using .findByStudent - // the error says that the function could not be found which is weird - // because typescript does not throw any errors - const classes = await classRepository.find( - { students: student }, - { populate: ["students", "teachers"] } // voegt student en teacher objecten toe - ) - // const classes = await classRepository.findByStudent(student); + const classes = await classRepository.findByStudent(student); if (!classes) return []; From 241fe0103f04761d436e36ba8c626611c60761b7 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Wed, 5 Mar 2025 16:31:27 +0100 Subject: [PATCH 07/49] feat: endpoints voor /, /:id en /:id/students in routes/class.ts zijn geimplementeerd --- backend/src/controllers/classes.ts | 29 +++++++++++++++++- backend/src/controllers/students.ts | 11 ++++--- backend/src/data/classes/class-repository.ts | 5 ++- backend/src/interfaces/students.ts | 11 +++++++ backend/src/routes/class.ts | 19 ++---------- backend/src/services/class.ts | 32 ++++++++++++++++++++ backend/src/services/students.ts | 22 +++++++------- 7 files changed, 95 insertions(+), 34 deletions(-) diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index f4c8666d..ee932734 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,5 +1,18 @@ import { Request, Response } from 'express'; -import { getClass } from '../services/class'; +import { getAllClasses, getClass, getClassStudents } from '../services/class'; +import { ClassDTO } from '../interfaces/classes'; + +export async function getAllClassesHandler( + req: Request, + res: Response, +): Promise { + const full = req.query.full === "true"; + const classes = await getAllClasses(full); + + res.json({ + classes: classes + }); +} export async function getClassHandler( req: Request, @@ -26,4 +39,18 @@ export async function getClassHandler( console.error('Error fetching learning objects:', error); res.status(500).json({ error: 'Internal server error' }); } +} + +export async function getClassStudentsHandler( + req: Request, + res: Response, +): Promise { + const classId = req.params.id; + const full = req.query.full === "true"; + + const students = await getClassStudents(classId, full); + + res.json({ + students: students, + }); } \ No newline at end of file diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 9b4b8f3c..c6973632 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,17 +1,18 @@ import { Request, Response } from 'express'; -import { getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; +import { getAllStudents, getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; import { ClassDTO } from '../interfaces/classes'; +// TODO: accept arguments (full, ...) +// TODO: endpoints export async function getAllStudentsHandler ( req: Request, res: Response, ): Promise { try { + const students = await getAllStudents(); + res.json({ - students: [ - '0', - '1', - ] + students: students }); } catch (error) { console.error('Error fetching learning objects:', error); diff --git a/backend/src/data/classes/class-repository.ts b/backend/src/data/classes/class-repository.ts index a9455323..cd0e44fc 100644 --- a/backend/src/data/classes/class-repository.ts +++ b/backend/src/data/classes/class-repository.ts @@ -4,7 +4,10 @@ import { Student } from '../../entities/users/student.entity.js'; export class ClassRepository extends DwengoEntityRepository { public findById(id: string): Promise { - return this.findOne({ classId: id }); + return this.findOne( + { classId: id }, + { populate: ["students", "teachers"] }, + ); } public deleteById(id: string): Promise { return this.deleteWhere({ classId: id }); diff --git a/backend/src/interfaces/students.ts b/backend/src/interfaces/students.ts index cb13d3c2..e87e707d 100644 --- a/backend/src/interfaces/students.ts +++ b/backend/src/interfaces/students.ts @@ -1,3 +1,5 @@ +import { Student } from "../entities/users/student.entity"; + export interface StudentDTO { id: string; username: string; @@ -10,3 +12,12 @@ export interface StudentDTO { groups: string; }; } + +export function mapToStudentDTO(student: Student): StudentDTO { + return { + id: student.username, + username: student.username, + firstName: student.firstName, + lastName: student.lastName, + }; +} \ No newline at end of file diff --git a/backend/src/routes/class.ts b/backend/src/routes/class.ts index 65ca9362..e58547b2 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/class.ts @@ -1,16 +1,9 @@ import express from 'express' -import { getClassHandler } from '../controllers/classes'; +import { getAllClassesHandler, getClassHandler, getClassStudentsHandler } from '../controllers/classes'; const router = express.Router(); // root endpoint used to search objects -router.get('/', (req, res) => { - res.json({ - classes: [ - '0', - '1', - ] - }); -}); +router.get('/', getAllClassesHandler); // information about an class with id 'id' router.get('/:id', getClassHandler); @@ -31,12 +24,6 @@ router.get('/:id/assignments', (req, res) => { }); }) -router.get('/:id/students', (req, res) => { - res.json({ - students: [ - '0' - ], - }); -}) +router.get('/:id/students', getClassStudentsHandler); export default router \ No newline at end of file diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 3a3e8322..89628404 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -1,5 +1,22 @@ import { getClassRepository } from "../data/repositories"; +import { Class } from "../entities/classes/class.entity"; import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; +import { mapToStudentDTO, StudentDTO } from "../interfaces/students"; + +export async function getAllClasses(full: boolean): Promise { + const classRepository = getClassRepository(); + const classes = await classRepository.find({}, { populate: ["students", "teachers"] }); + + if (!classes) { + return []; + } + + if (full) { + return classes.map(mapToClassDTO); + } else { + return classes.map((cls) => cls.classId); + } +} export async function getClass(classId: string): Promise { const classRepository = getClassRepository(); @@ -9,4 +26,19 @@ export async function getClass(classId: string): Promise { else { return mapToClassDTO(cls); } +} + +export async function getClassStudents(classId: string, full: boolean): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classId); + + if (!cls) { + return []; + } + + if (full) { + return cls.students.map(mapToStudentDTO); + } else { + return cls.students.map((student) => student.username); + } } \ No newline at end of file diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 3a1b601f..a69cab85 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,26 +1,26 @@ import { getClassRepository, getStudentRepository } from "../data/repositories"; import { Class } from "../entities/classes/class.entity"; +import { Student } from "../entities/users/student.entity"; import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; -import { StudentDTO } from "../interfaces/students"; +import { StudentDTO, mapToStudentDTO } from "../interfaces/students"; + export async function getAllStudents(): Promise { - // TODO - return []; + const studentRepository = getStudentRepository(); + const students = await studentRepository.find({}); + + return students.map(mapToStudentDTO); } export async function getStudent(username: string): Promise { const studentRepository = getStudentRepository(); const student = await studentRepository.findByUsername(username); - if (!student) return null; - else { - return { - id: student.username, - username: student.username, - firstName: student.firstName, - lastName: student.lastName, - } + if (!student) { + return null; } + + return mapToStudentDTO(student); } async function fetchStudentClasses(username: string): Promise { From cfd0cce2df839f8499cf729c0a948533b293e8dd Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Wed, 5 Mar 2025 17:45:09 +0100 Subject: [PATCH 08/49] feat: gestart met implementeren van assignment service en controller laag --- backend/src/app.ts | 2 -- backend/src/controllers/assignments.ts | 30 ++++++++++++++++++++++++++ backend/src/interfaces/assignments.ts | 25 +++++++++++++++++++++ backend/src/interfaces/groups.ts | 3 +++ backend/src/interfaces/list.ts | 5 +++++ backend/src/routes/assignment.ts | 20 +++++------------ backend/src/routes/class.ts | 12 ++++------- backend/src/services/assignments.ts | 20 +++++++++++++++++ 8 files changed, 92 insertions(+), 25 deletions(-) create mode 100644 backend/src/controllers/assignments.ts create mode 100644 backend/src/interfaces/assignments.ts create mode 100644 backend/src/interfaces/groups.ts create mode 100644 backend/src/interfaces/list.ts create mode 100644 backend/src/services/assignments.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index b21bb9f1..e4da44e7 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -8,7 +8,6 @@ import learningObjectRoutes from './routes/learningObjects.js'; import studentRouter from './routes/student.js'; import groupRouter from './routes/group.js'; -import assignmentRouter from './routes/assignment.js'; import submissionRouter from './routes/submission.js'; import classRouter from './routes/class.js'; import questionRouter from './routes/question.js'; @@ -27,7 +26,6 @@ app.get('/', (_, res: Response) => { app.use('/student', studentRouter); app.use('/group', groupRouter); -app.use('/assignment', assignmentRouter); app.use('/submission', submissionRouter); app.use('/class', classRouter); app.use('/question', questionRouter); diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts new file mode 100644 index 00000000..775a60df --- /dev/null +++ b/backend/src/controllers/assignments.ts @@ -0,0 +1,30 @@ +import { Request, Response } from 'express' +import { getAssignment } from '../services/assignments'; + +// typescript is annoywith with parameter forwarding from class.ts +interface AssignmentParams { + classid: string; + id: string; +} + +export async function getAssignmentHandler( + req: Request, + res: Response, +): Promise { + const id = +req.params.id; + const classid = req.params.classid; + + if (isNaN(id)) { + res.status(400).json({ error: "Assignment id must be a number" }); + return; + } + + const assignment = await getAssignment(classid, id); + + if (!assignment) { + res.status(404).json({ error: "Assignment not found" }); + return; + } + + res.json(assignment); +} \ No newline at end of file diff --git a/backend/src/interfaces/assignments.ts b/backend/src/interfaces/assignments.ts new file mode 100644 index 00000000..a3c3c4cc --- /dev/null +++ b/backend/src/interfaces/assignments.ts @@ -0,0 +1,25 @@ +import { Assignment } from "../entities/assignments/assignment.entity"; +import { Class } from "../entities/classes/class.entity"; +import { GroupDTO } from "./groups"; + +export interface AssignmentDTO { + id: number, + class: string, // id of class 'within' + title: string, + description: string, + learningPath: string, + language: string, + groups?: GroupDTO[], // TODO +} + +export function mapToAssignmentDTO(assignment: Assignment, cls: Class): AssignmentDTO { + return { + id: assignment.id, + class: cls.classId, + title: assignment.title, + description: assignment.description, + learningPath: assignment.learningPathHruid, + language: assignment.learningPathLanguage, + //groups: assignment.groups.map(mapToGroupDTO), + }; +} \ No newline at end of file diff --git a/backend/src/interfaces/groups.ts b/backend/src/interfaces/groups.ts new file mode 100644 index 00000000..6056a906 --- /dev/null +++ b/backend/src/interfaces/groups.ts @@ -0,0 +1,3 @@ +export interface GroupDTO { + groupNumber: number, +} \ No newline at end of file diff --git a/backend/src/interfaces/list.ts b/backend/src/interfaces/list.ts new file mode 100644 index 00000000..0037403d --- /dev/null +++ b/backend/src/interfaces/list.ts @@ -0,0 +1,5 @@ +// TODO: implement something like this but with named endpoints +export interface List { + items: T[], + endpoints?: string[], +}; \ No newline at end of file diff --git a/backend/src/routes/assignment.ts b/backend/src/routes/assignment.ts index fcb6e9da..e9c91160 100644 --- a/backend/src/routes/assignment.ts +++ b/backend/src/routes/assignment.ts @@ -1,5 +1,8 @@ import express from 'express' -const router = express.Router(); +import { getAssignmentHandler } from '../controllers/assignments'; +const router = express.Router({ mergeParams: true }); + + // root endpoint used to search objects router.get('/', (req, res) => { @@ -12,20 +15,7 @@ router.get('/', (req, res) => { }); // information about an assignment with id 'id' -router.get('/:id', (req, res) => { - res.json({ - id: req.params.id, - title: 'Dit is een test assignment', - description: 'Een korte beschrijving', - groups: [ '0' ], - learningPath: '0', - class: '0', - links: { - self: `${req.baseUrl}/${req.params.id}`, - submissions: `${req.baseUrl}/${req.params.id}`, - }, - }); -}) +router.get('/:id', getAssignmentHandler); router.get('/:id/submissions', (req, res) => { res.json({ diff --git a/backend/src/routes/class.ts b/backend/src/routes/class.ts index e58547b2..bc502fb8 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/class.ts @@ -1,5 +1,7 @@ import express from 'express' import { getAllClassesHandler, getClassHandler, getClassStudentsHandler } from '../controllers/classes'; +import assignmentRouter from './assignment.js'; + const router = express.Router(); // root endpoint used to search objects @@ -16,14 +18,8 @@ router.get('/:id/invitations', (req, res) => { }); }) -router.get('/:id/assignments', (req, res) => { - res.json({ - assignments: [ - '0' - ], - }); -}) - router.get('/:id/students', getClassStudentsHandler); +router.use('/:classid/assignments', assignmentRouter); + export default router \ No newline at end of file diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts new file mode 100644 index 00000000..ab76f6a8 --- /dev/null +++ b/backend/src/services/assignments.ts @@ -0,0 +1,20 @@ +import { getAssignmentRepository, getClassRepository } from "../data/repositories"; +import { AssignmentDTO, mapToAssignmentDTO } from "../interfaces/assignments"; + +export async function getAssignment(classid: string, id: number): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classid); + + if (!cls) { + return null; + } + + const assignmentRepository = getAssignmentRepository(); + const assignment = await assignmentRepository.findByClassAndId(cls, id); + + if (!assignment) { + return null; + } + + return mapToAssignmentDTO(assignment, cls); +} \ No newline at end of file From 037763a810836e00db5a7f4bf5986fa6395e2f14 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 10:47:20 +0100 Subject: [PATCH 09/49] fix: verwijder login route --- backend/src/app.ts | 2 -- backend/src/routes/login.ts | 14 -------------- 2 files changed, 16 deletions(-) delete mode 100644 backend/src/routes/login.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index e4da44e7..83b4b998 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -11,7 +11,6 @@ import groupRouter from './routes/group.js'; import submissionRouter from './routes/submission.js'; import classRouter from './routes/class.js'; import questionRouter from './routes/question.js'; -import loginRouter from './routes/login.js'; const app: Express = express(); const port: string | number = getNumericEnvVar(EnvVars.Port); @@ -29,7 +28,6 @@ app.use('/group', groupRouter); app.use('/submission', submissionRouter); app.use('/class', classRouter); app.use('/question', questionRouter); -app.use('/login', loginRouter); app.use('/theme', themeRoutes); app.use('/learningPath', learningPathRoutes); diff --git a/backend/src/routes/login.ts b/backend/src/routes/login.ts deleted file mode 100644 index 550e6d93..00000000 --- a/backend/src/routes/login.ts +++ /dev/null @@ -1,14 +0,0 @@ -import express from 'express' -const router = express.Router(); - -// returns login paths for IDP -router.get('/', (req, res) => { - res.json({ - // dummy variables, needs to be changed - // with IDP endpoints - leerkracht: '/login-leerkracht', - leerling: '/login-leerling', - }); -}) - -export default router \ No newline at end of file From 3b71c80be6c5041078ad97688acfb909b74a521e Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 10:55:44 +0100 Subject: [PATCH 10/49] fix: consistente naamgeving --- backend/src/app.ts | 24 +++++++++---------- backend/src/controllers/assignments.ts | 4 ++-- .../routes/{assignment.ts => assignments.ts} | 0 backend/src/routes/{class.ts => classes.ts} | 6 ++--- backend/src/routes/{group.ts => groups.ts} | 0 ...learningObjects.ts => learning-objects.ts} | 0 .../{learningPaths.ts => learning-paths.ts} | 0 .../src/routes/{question.ts => questions.ts} | 0 .../src/routes/{student.ts => students.ts} | 0 .../routes/{submission.ts => submissions.ts} | 0 .../src/routes/{teacher.ts => teachers.ts} | 0 11 files changed, 17 insertions(+), 17 deletions(-) rename backend/src/routes/{assignment.ts => assignments.ts} (100%) rename backend/src/routes/{class.ts => classes.ts} (85%) rename backend/src/routes/{group.ts => groups.ts} (100%) rename backend/src/routes/{learningObjects.ts => learning-objects.ts} (100%) rename backend/src/routes/{learningPaths.ts => learning-paths.ts} (100%) rename backend/src/routes/{question.ts => questions.ts} (100%) rename backend/src/routes/{student.ts => students.ts} (100%) rename backend/src/routes/{submission.ts => submissions.ts} (100%) rename backend/src/routes/{teacher.ts => teachers.ts} (100%) diff --git a/backend/src/app.ts b/backend/src/app.ts index 83b4b998..811c6cfc 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -3,14 +3,14 @@ import { initORM } from './orm.js'; import { EnvVars, getNumericEnvVar } from './util/envvars.js'; import themeRoutes from './routes/themes.js'; -import learningPathRoutes from './routes/learningPaths.js'; -import learningObjectRoutes from './routes/learningObjects.js'; +import learningPathRoutes from './routes/learning-paths.js'; +import learningObjectRoutes from './routes/learning-objects.js'; -import studentRouter from './routes/student.js'; -import groupRouter from './routes/group.js'; -import submissionRouter from './routes/submission.js'; -import classRouter from './routes/class.js'; -import questionRouter from './routes/question.js'; +import studentRoutes from './routes/students.js'; +import groupRoutes from './routes/groups.js'; +import submissionRoutes from './routes/submissions.js'; +import classRoutes from './routes/classes.js'; +import questionRoutes from './routes/questions.js'; const app: Express = express(); const port: string | number = getNumericEnvVar(EnvVars.Port); @@ -23,11 +23,11 @@ app.get('/', (_, res: Response) => { }); }); -app.use('/student', studentRouter); -app.use('/group', groupRouter); -app.use('/submission', submissionRouter); -app.use('/class', classRouter); -app.use('/question', questionRouter); +app.use('/student', studentRoutes); +app.use('/group', groupRoutes); +app.use('/submission', submissionRoutes); +app.use('/class', classRoutes); +app.use('/question', questionRoutes); app.use('/theme', themeRoutes); app.use('/learningPath', learningPathRoutes); diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 775a60df..feabb1e1 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,7 +1,7 @@ import { Request, Response } from 'express' import { getAssignment } from '../services/assignments'; -// typescript is annoywith with parameter forwarding from class.ts +// typescript is annoywith with parameter forwarding from classes.ts interface AssignmentParams { classid: string; id: string; @@ -27,4 +27,4 @@ export async function getAssignmentHandler( } res.json(assignment); -} \ No newline at end of file +} diff --git a/backend/src/routes/assignment.ts b/backend/src/routes/assignments.ts similarity index 100% rename from backend/src/routes/assignment.ts rename to backend/src/routes/assignments.ts diff --git a/backend/src/routes/class.ts b/backend/src/routes/classes.ts similarity index 85% rename from backend/src/routes/class.ts rename to backend/src/routes/classes.ts index bc502fb8..420018a4 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/classes.ts @@ -1,6 +1,6 @@ import express from 'express' import { getAllClassesHandler, getClassHandler, getClassStudentsHandler } from '../controllers/classes'; -import assignmentRouter from './assignment.js'; +import assignmentRouter from './assignments.js'; const router = express.Router(); @@ -12,7 +12,7 @@ router.get('/:id', getClassHandler); router.get('/:id/invitations', (req, res) => { res.json({ - invitations: [ + invitations: [ '0' ], }); @@ -22,4 +22,4 @@ router.get('/:id/students', getClassStudentsHandler); router.use('/:classid/assignments', assignmentRouter); -export default router \ No newline at end of file +export default router diff --git a/backend/src/routes/group.ts b/backend/src/routes/groups.ts similarity index 100% rename from backend/src/routes/group.ts rename to backend/src/routes/groups.ts diff --git a/backend/src/routes/learningObjects.ts b/backend/src/routes/learning-objects.ts similarity index 100% rename from backend/src/routes/learningObjects.ts rename to backend/src/routes/learning-objects.ts diff --git a/backend/src/routes/learningPaths.ts b/backend/src/routes/learning-paths.ts similarity index 100% rename from backend/src/routes/learningPaths.ts rename to backend/src/routes/learning-paths.ts diff --git a/backend/src/routes/question.ts b/backend/src/routes/questions.ts similarity index 100% rename from backend/src/routes/question.ts rename to backend/src/routes/questions.ts diff --git a/backend/src/routes/student.ts b/backend/src/routes/students.ts similarity index 100% rename from backend/src/routes/student.ts rename to backend/src/routes/students.ts diff --git a/backend/src/routes/submission.ts b/backend/src/routes/submissions.ts similarity index 100% rename from backend/src/routes/submission.ts rename to backend/src/routes/submissions.ts diff --git a/backend/src/routes/teacher.ts b/backend/src/routes/teachers.ts similarity index 100% rename from backend/src/routes/teacher.ts rename to backend/src/routes/teachers.ts From b8db32161f633a1734a44614c670e4d7697b6e51 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 20:04:46 +0100 Subject: [PATCH 11/49] fix: consistente naamgeving kebab case --- ...{learningObjects.ts => learning-objects.ts} | 4 ++-- .../{learningPaths.ts => learning-paths.ts} | 2 +- backend/src/controllers/themes.ts | 2 +- .../entities/content/learning-object.entity.ts | 18 +++++++++--------- .../{learningPath.ts => learning-path.ts} | 0 backend/src/routes/learning-objects.ts | 2 +- backend/src/routes/learning-paths.ts | 2 +- ...{learningObjects.ts => learning-objects.ts} | 6 +++--- .../{learningPaths.ts => learning-paths.ts} | 4 ++-- .../src/util/{apiHelper.ts => api-helper.ts} | 0 ...nslationHelper.ts => translation-helper.ts} | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) rename backend/src/controllers/{learningObjects.ts => learning-objects.ts} (93%) rename backend/src/controllers/{learningPaths.ts => learning-paths.ts} (97%) rename backend/src/interfaces/{learningPath.ts => learning-path.ts} (100%) rename backend/src/services/{learningObjects.ts => learning-objects.ts} (96%) rename backend/src/services/{learningPaths.ts => learning-paths.ts} (93%) rename backend/src/util/{apiHelper.ts => api-helper.ts} (100%) rename backend/src/util/{translationHelper.ts => translation-helper.ts} (93%) diff --git a/backend/src/controllers/learningObjects.ts b/backend/src/controllers/learning-objects.ts similarity index 93% rename from backend/src/controllers/learningObjects.ts rename to backend/src/controllers/learning-objects.ts index 4295326a..c8a51734 100644 --- a/backend/src/controllers/learningObjects.ts +++ b/backend/src/controllers/learning-objects.ts @@ -3,9 +3,9 @@ import { getLearningObjectById, getLearningObjectIdsFromPath, getLearningObjectsFromPath, -} from '../services/learningObjects.js'; +} from '../services/learning-objects.js'; import { FALLBACK_LANG } from '../config.js'; -import { FilteredLearningObject } from '../interfaces/learningPath'; +import { FilteredLearningObject } from '../interfaces/learning-path'; export async function getAllLearningObjects( req: Request, diff --git a/backend/src/controllers/learningPaths.ts b/backend/src/controllers/learning-paths.ts similarity index 97% rename from backend/src/controllers/learningPaths.ts rename to backend/src/controllers/learning-paths.ts index 903451be..fb0fd07c 100644 --- a/backend/src/controllers/learningPaths.ts +++ b/backend/src/controllers/learning-paths.ts @@ -4,7 +4,7 @@ import { FALLBACK_LANG } from '../config.js'; import { fetchLearningPaths, searchLearningPaths, -} from '../services/learningPaths.js'; +} from '../services/learning-paths.js'; /** * Fetch learning paths based on query parameters. */ diff --git a/backend/src/controllers/themes.ts b/backend/src/controllers/themes.ts index 4b59751e..208b27d1 100644 --- a/backend/src/controllers/themes.ts +++ b/backend/src/controllers/themes.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; import { themes } from '../data/themes.js'; -import { loadTranslations } from "../util/translationHelper.js"; +import { loadTranslations } from "../util/translation-helper.js"; import { FALLBACK_LANG } from '../config.js'; interface Translations { diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index 179a2f5f..78d4aa00 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -13,6 +13,15 @@ import { Attachment } from './attachment.entity.js'; import { Teacher } from '../users/teacher.entity.js'; import { LearningObjectRepository } from '../../data/content/learning-object-repository.js'; +@Embeddable() +export class ReturnValue { + @Property({ type: 'string' }) + callbackUrl!: string; + + @Property({ type: 'json' }) + callbackSchema!: string; +} + @Entity({ repository: () => LearningObjectRepository }) export class LearningObject { @PrimaryKey({ type: 'string' }) @@ -88,15 +97,6 @@ export class EducationalGoal { id!: string; } -@Embeddable() -export class ReturnValue { - @Property({ type: 'string' }) - callbackUrl!: string; - - @Property({ type: 'json' }) - callbackSchema!: string; -} - export enum ContentType { Markdown = 'text/markdown', Image = 'image/image', diff --git a/backend/src/interfaces/learningPath.ts b/backend/src/interfaces/learning-path.ts similarity index 100% rename from backend/src/interfaces/learningPath.ts rename to backend/src/interfaces/learning-path.ts diff --git a/backend/src/routes/learning-objects.ts b/backend/src/routes/learning-objects.ts index 416602b5..3717095a 100644 --- a/backend/src/routes/learning-objects.ts +++ b/backend/src/routes/learning-objects.ts @@ -2,7 +2,7 @@ import express from 'express'; import { getAllLearningObjects, getLearningObject, -} from '../controllers/learningObjects.js'; +} from '../controllers/learning-objects.js'; const router = express.Router(); diff --git a/backend/src/routes/learning-paths.ts b/backend/src/routes/learning-paths.ts index ce580745..efe17312 100644 --- a/backend/src/routes/learning-paths.ts +++ b/backend/src/routes/learning-paths.ts @@ -1,5 +1,5 @@ import express from 'express'; -import { getLearningPaths } from '../controllers/learningPaths.js'; +import { getLearningPaths } from '../controllers/learning-paths.js'; const router = express.Router(); diff --git a/backend/src/services/learningObjects.ts b/backend/src/services/learning-objects.ts similarity index 96% rename from backend/src/services/learningObjects.ts rename to backend/src/services/learning-objects.ts index d1d34ad2..65ad11a6 100644 --- a/backend/src/services/learningObjects.ts +++ b/backend/src/services/learning-objects.ts @@ -1,12 +1,12 @@ import { DWENGO_API_BASE } from '../config.js'; -import { fetchWithLogging } from '../util/apiHelper.js'; +import { fetchWithLogging } from '../util/api-helper.js'; import { FilteredLearningObject, LearningObjectMetadata, LearningObjectNode, LearningPathResponse, -} from '../interfaces/learningPath.js'; -import { fetchLearningPaths } from './learningPaths.js'; +} from '../interfaces/learning-path.js'; +import { fetchLearningPaths } from './learning-paths.js'; function filterData( data: LearningObjectMetadata, diff --git a/backend/src/services/learningPaths.ts b/backend/src/services/learning-paths.ts similarity index 93% rename from backend/src/services/learningPaths.ts rename to backend/src/services/learning-paths.ts index 2a9f15a3..3353b58d 100644 --- a/backend/src/services/learningPaths.ts +++ b/backend/src/services/learning-paths.ts @@ -1,9 +1,9 @@ -import { fetchWithLogging } from '../util/apiHelper.js'; +import { fetchWithLogging } from '../util/api-helper.js'; import { DWENGO_API_BASE } from '../config.js'; import { LearningPath, LearningPathResponse, -} from '../interfaces/learningPath.js'; +} from '../interfaces/learning-path.js'; export async function fetchLearningPaths( hruids: string[], diff --git a/backend/src/util/apiHelper.ts b/backend/src/util/api-helper.ts similarity index 100% rename from backend/src/util/apiHelper.ts rename to backend/src/util/api-helper.ts diff --git a/backend/src/util/translationHelper.ts b/backend/src/util/translation-helper.ts similarity index 93% rename from backend/src/util/translationHelper.ts rename to backend/src/util/translation-helper.ts index f4443531..d6d842ff 100644 --- a/backend/src/util/translationHelper.ts +++ b/backend/src/util/translation-helper.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import yaml from 'js-yaml'; -import {FALLBACK_LANG} from "../../config"; +import { FALLBACK_LANG } from "../config.js"; export function loadTranslations(language: string): T { try { From 6b87722469e2afd1671336e4c988690fcdf6ce57 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 20:05:16 +0100 Subject: [PATCH 12/49] feat: teacher get, post en delete route --- backend/src/app.ts | 4 + backend/src/controllers/teachers.ts | 79 ++++++++++++++++++++ backend/src/data/users/teacher-repository.ts | 3 + backend/src/interfaces/teacher.ts | 36 +++++++++ backend/src/routes/teachers.ts | 30 ++------ backend/src/services/teachers.ts | 38 ++++++++++ 6 files changed, 166 insertions(+), 24 deletions(-) create mode 100644 backend/src/controllers/teachers.ts create mode 100644 backend/src/interfaces/teacher.ts create mode 100644 backend/src/services/teachers.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index 811c6cfc..f28604c0 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -7,6 +7,7 @@ import learningPathRoutes from './routes/learning-paths.js'; import learningObjectRoutes from './routes/learning-objects.js'; import studentRoutes from './routes/students.js'; +import teacherRoutes from './routes/teachers.js' import groupRoutes from './routes/groups.js'; import submissionRoutes from './routes/submissions.js'; import classRoutes from './routes/classes.js'; @@ -16,6 +17,8 @@ const app: Express = express(); const port: string | number = getNumericEnvVar(EnvVars.Port); +app.use(express.json()); + // TODO Replace with Express routes app.get('/', (_, res: Response) => { res.json({ @@ -24,6 +27,7 @@ app.get('/', (_, res: Response) => { }); app.use('/student', studentRoutes); +app.use('/teacher', teacherRoutes); app.use('/group', groupRoutes); app.use('/submission', submissionRoutes); app.use('/class', classRoutes); diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts new file mode 100644 index 00000000..d4baef2f --- /dev/null +++ b/backend/src/controllers/teachers.ts @@ -0,0 +1,79 @@ +import { Request, Response } from 'express'; +import { + createTeacher, deleteTeacher, + fetchAllTeachers, fetchTeacherByUsername +} from '../services/teachers.js'; +import {TeacherDTO} from "../interfaces/teacher"; + +export async function getTeacherHandler(req: Request, res: Response): Promise { + try { + const full = req.query.full === 'true'; + const username = req.query.username as string; + + if (username){ + const teacher = await fetchTeacherByUsername(username); + if (!teacher){ + res.status(404).json({ error: `Teacher with username '${username}' not found.` }); + return; + } + res.json(teacher); + return; + } + + let teachers: TeacherDTO[] | string[] = await fetchAllTeachers(); + + if (!full) + teachers = teachers.map((teacher) => teacher.username) + + res.json(teachers); + } catch (error) { + console.error("❌ Error fetching teachers:", error); + res.status(500).json({ error: "Internal server error" }); + } +} + +export async function createTeacherHandler( + req: Request, + res: Response +): Promise { + try { + const teacherData = req.body as TeacherDTO; + + if (!teacherData.username || !teacherData.firstName || !teacherData.lastName) { + res.status(400).json({ error: 'Missing required fields: username, firstName, lastName' }); + return; + } + + const newTeacher = await createTeacher(teacherData); + res.status(201).json(newTeacher); + } catch (error) { + console.error('Error creating teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +export async function deleteTeacherHandler( + req: Request, + res: Response +): Promise { + try { + const username = req.params.username as string; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + const deletedTeacher = await deleteTeacher(username); + + if (!deletedTeacher) { + res.status(400).json({ error: `Did not find teacher with username ${username}` }); + return; + } + + res.status(201).json(deletedTeacher); + } catch (error) { + console.error('Error deleting teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} diff --git a/backend/src/data/users/teacher-repository.ts b/backend/src/data/users/teacher-repository.ts index 704ef409..43602ff7 100644 --- a/backend/src/data/users/teacher-repository.ts +++ b/backend/src/data/users/teacher-repository.ts @@ -5,6 +5,9 @@ export class TeacherRepository extends DwengoEntityRepository { public findByUsername(username: string): Promise { return this.findOne({ username: username }); } + public addTeacher(teacher: Teacher): Promise { + return this.save(teacher); + } public deleteByUsername(username: string): Promise { return this.deleteWhere({ username: username }); } diff --git a/backend/src/interfaces/teacher.ts b/backend/src/interfaces/teacher.ts new file mode 100644 index 00000000..15c89520 --- /dev/null +++ b/backend/src/interfaces/teacher.ts @@ -0,0 +1,36 @@ +import { Teacher } from "../entities/users/teacher.entity.js"; + +/** + * Teacher Data Transfer Object + */ +export interface TeacherDTO { + username: string; + firstName: string; + lastName: string; + endpoints?: { + self: string; + classes: string; + questions: string; + invitations: string; + }; +} + +/** + * Maps a Teacher entity to a TeacherDTO + */ +export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { + return { + username: teacher.username, + firstName: teacher.firstName, + lastName: teacher.lastName, + }; +} + +export function mapToTeacher(teacherData: TeacherDTO): Teacher { + const teacher = new Teacher(); + teacher.username = teacherData.username; + teacher.firstName = teacherData.firstName; + teacher.lastName = teacherData.lastName; + + return teacher; +} diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index 37b3b04b..dab98dea 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -1,31 +1,13 @@ import express from 'express' +import {createTeacherHandler, deleteTeacherHandler, getTeacherHandler} from "../controllers/teachers.js"; const router = express.Router(); // root endpoint used to search objects -router.get('/', (req, res) => { - res.json({ - teachers: [ - '0', - '1', - ] - }); -}); +router.get('/', getTeacherHandler); -// information about a teacher -router.get('/:id', (req, res) => { - res.json({ - id: req.params.id, - firstName: 'John', - lastName: 'Doe', - username: 'JohnDoe1', - links: { - self: `${req.baseUrl}/${req.params.id}`, - classes: `${req.baseUrl}/${req.params.id}/classes`, - questions: `${req.baseUrl}/${req.params.id}/questions`, - invitations: `${req.baseUrl}/${req.params.id}/invitations`, - }, - }); -}) +router.post('/', createTeacherHandler); + +router.delete('/:username', deleteTeacherHandler); // the questions students asked a teacher router.get('/:id/questions', (req, res) => { @@ -55,4 +37,4 @@ router.get('/:id/classes', (req, res) => { }); -export default router \ No newline at end of file +export default router diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts new file mode 100644 index 00000000..5572d4b0 --- /dev/null +++ b/backend/src/services/teachers.ts @@ -0,0 +1,38 @@ +import {getTeacherRepository} from "../data/repositories.js"; +import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; +import { Teacher } from "../entities/users/teacher.entity"; + + +export async function fetchAllTeachers(): Promise { + const teacherRepository = getTeacherRepository(); + const teachers = await teacherRepository.find({}); + + return teachers.map(mapToTeacherDTO); +} + +export async function createTeacher(teacherData: TeacherDTO): Promise { + const teacherRepository = getTeacherRepository(); + const newTeacher = mapToTeacher(teacherData); + + await teacherRepository.addTeacher(newTeacher); + return newTeacher; +} + +export async function fetchTeacherByUsername(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const teacher = await teacherRepository.findByUsername(username); + + return teacher ? mapToTeacherDTO(teacher) : null; +} + +export async function deleteTeacher(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const teacher = await teacherRepository.findByUsername(username); + + if (!teacher) + return null; + + await teacherRepository.deleteByUsername(username); + return teacher; +} + From 9c9e7c4870954c03274f2f503faeef19f50d97dc Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 7 Mar 2025 23:09:51 +0100 Subject: [PATCH 13/49] feat: teacher-class en teacher-students route --- backend/src/controllers/classes.ts | 9 ++- backend/src/controllers/teachers.ts | 61 ++++++++++++++++++-- backend/src/data/classes/class-repository.ts | 8 +++ backend/src/routes/teachers.ts | 11 +++- backend/src/services/class.ts | 24 ++++---- backend/src/services/teachers.ts | 54 ++++++++++++++++- 6 files changed, 146 insertions(+), 21 deletions(-) diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index ee932734..c8095162 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import { getAllClasses, getClass, getClassStudents } from '../services/class'; +import {getAllClasses, getClass, getClassStudents, getClassStudentsIds} from '../services/class'; import { ClassDTO } from '../interfaces/classes'; export async function getAllClassesHandler( @@ -48,9 +48,12 @@ export async function getClassStudentsHandler( const classId = req.params.id; const full = req.query.full === "true"; - const students = await getClassStudents(classId, full); + let students; + + if (full) students = await getClassStudents(classId); + else students = await getClassStudentsIds(classId); res.json({ students: students, }); -} \ No newline at end of file +} diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index d4baef2f..6f363c20 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -1,9 +1,16 @@ import { Request, Response } from 'express'; import { - createTeacher, deleteTeacher, - fetchAllTeachers, fetchTeacherByUsername + createTeacher, + deleteTeacher, + fetchTeacherByUsername, + getClassesByTeacher, + getClassIdsByTeacher, + getAllTeachers, + getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher } from '../services/teachers.js'; import {TeacherDTO} from "../interfaces/teacher"; +import {ClassDTO} from "../interfaces/classes"; +import {StudentDTO} from "../interfaces/students"; export async function getTeacherHandler(req: Request, res: Response): Promise { try { @@ -20,10 +27,10 @@ export async function getTeacherHandler(req: Request, res: Response): Promise teacher.username) + if (full) teachers = await getAllTeachers(); + else teachers = await getAllTeachersIds(); res.json(teachers); } catch (error) { @@ -77,3 +84,47 @@ export async function deleteTeacherHandler( res.status(500).json({ error: 'Internal server error' }); } } + +export async function getTeacherClassHandler(req: Request, res: Response): Promise { + try { + const username = req.params.username as string; + const full = req.query.full === 'true'; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + let classes: ClassDTO[] | string[]; + + if (full) classes = await getClassesByTeacher(username); + else classes = await getClassIdsByTeacher(username); + + res.status(201).json(classes); + } catch (error) { + console.error('Error fetching classes by teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +export async function getTeacherStudentHandler(req: Request, res: Response): Promise { + try { + const username = req.params.username as string; + const full = req.query.full === 'true'; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + let students: StudentDTO[] | string[]; + + if (full) students = await getStudentsByTeacher(username); + else students = await getStudentIdsByTeacher(username); + + res.status(201).json(students); + } catch (error) { + console.error('Error fetching students by teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} diff --git a/backend/src/data/classes/class-repository.ts b/backend/src/data/classes/class-repository.ts index cd0e44fc..9fd50d75 100644 --- a/backend/src/data/classes/class-repository.ts +++ b/backend/src/data/classes/class-repository.ts @@ -1,6 +1,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Class } from '../../entities/classes/class.entity.js'; import { Student } from '../../entities/users/student.entity.js'; +import {Teacher} from "../../entities/users/teacher.entity"; export class ClassRepository extends DwengoEntityRepository { public findById(id: string): Promise { @@ -18,4 +19,11 @@ export class ClassRepository extends DwengoEntityRepository { { populate: ["students", "teachers"] } // voegt student en teacher objecten toe ) } + + public findByTeacher(teacher: Teacher): Promise { + return this.find( + { teachers: teacher }, + { populate: ["students", "teachers"] } + ); + } } diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index dab98dea..338ac0b8 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -1,5 +1,10 @@ import express from 'express' -import {createTeacherHandler, deleteTeacherHandler, getTeacherHandler} from "../controllers/teachers.js"; +import { + createTeacherHandler, + deleteTeacherHandler, + getTeacherClassHandler, + getTeacherHandler, getTeacherStudentHandler +} from "../controllers/teachers.js"; const router = express.Router(); // root endpoint used to search objects @@ -9,6 +14,10 @@ router.post('/', createTeacherHandler); router.delete('/:username', deleteTeacherHandler); +router.get('/:username/classes', getTeacherClassHandler); + +router.get('/:username/students', getTeacherStudentHandler); + // the questions students asked a teacher router.get('/:id/questions', (req, res) => { res.json({ diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 89628404..56d939ae 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -10,7 +10,7 @@ export async function getAllClasses(full: boolean): Promise { } } -export async function getClassStudents(classId: string, full: boolean): Promise { +async function fetchClassStudents(classId: string, full: boolean): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); - if (!cls) { + if (!cls) return []; - } - if (full) { - return cls.students.map(mapToStudentDTO); - } else { - return cls.students.map((student) => student.username); - } -} \ No newline at end of file + return cls.students.map(mapToStudentDTO); +} + +export async function getClassStudents(classId: string): Promise { + return await fetchClassStudents(classId); +} + +export async function getClassStudentsIds(classId: string): Promise { + return await fetchClassStudents(classId).map((student) => student.username); +} + diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 5572d4b0..39ee3997 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -1,15 +1,26 @@ -import {getTeacherRepository} from "../data/repositories.js"; +import {getClassRepository, getTeacherRepository} from "../data/repositories.js"; import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; import { Teacher } from "../entities/users/teacher.entity"; +import {ClassDTO, mapToClassDTO} from "../interfaces/classes"; +import {getClassStudents, getClassStudentsIds} from "./class"; +import {StudentDTO} from "../interfaces/students"; -export async function fetchAllTeachers(): Promise { +async function fetchAllTeachers(): Promise { const teacherRepository = getTeacherRepository(); const teachers = await teacherRepository.find({}); return teachers.map(mapToTeacherDTO); } +export async function getAllTeachers(): Promise { + return await fetchAllTeachers(); +} + +export async function getAllTeachersIds(): Promise { + return await fetchAllTeachers().map((teacher) => teacher.username) +} + export async function createTeacher(teacherData: TeacherDTO): Promise { const teacherRepository = getTeacherRepository(); const newTeacher = mapToTeacher(teacherData); @@ -36,3 +47,42 @@ export async function deleteTeacher(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const classRepository = getClassRepository(); + + const teacher = await teacherRepository.findByUsername(username); + if (!teacher) { + return []; + } + + const classes = await classRepository.findByTeacher(teacher); + return classes.map(mapToClassDTO); +} + +export async function getClassesByTeacher(username: string): Promise { + return await fetchClassesByTeacher(username) +} + +export async function getClassIdsByTeacher(): Promise { + return await fetchClassesByTeacher(username).map((cls) => cls.id); +} + +async function fetchStudentsByTeacher(username: string) { + const classes = await getClassIdsByTeacher(); + + return Promise.all( + classes.map( async (id) => getClassStudents(id)) + ); +} + +export async function getStudentsByTeacher(username: string): Promise { + return await fetchStudentsByTeacher(username); +} + +export async function getStudentIdsByTeacher(): Promise { + return await fetchStudentsByTeacher(username).map((student) => student.username); +} + + + From 4968d7cb077b885ee90ba0896262e684762c0ae0 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Sat, 8 Mar 2025 09:36:03 +0100 Subject: [PATCH 14/49] fix: interface bestanden enkelvoud --- backend/src/controllers/assignments.ts | 2 +- backend/src/controllers/classes.ts | 2 +- backend/src/controllers/students.ts | 6 +++--- backend/src/controllers/teachers.ts | 4 ++-- backend/src/interfaces/{assignments.ts => assignment.ts} | 4 ++-- backend/src/interfaces/{classes.ts => class.ts} | 0 backend/src/interfaces/{groups.ts => group.ts} | 0 backend/src/interfaces/{students.ts => student.ts} | 0 backend/src/services/assignments.ts | 6 +++--- backend/src/services/class.ts | 4 ++-- backend/src/services/students.ts | 8 ++++---- backend/src/services/teachers.ts | 4 ++-- 12 files changed, 20 insertions(+), 20 deletions(-) rename backend/src/interfaces/{assignments.ts => assignment.ts} (95%) rename backend/src/interfaces/{classes.ts => class.ts} (100%) rename backend/src/interfaces/{groups.ts => group.ts} (100%) rename backend/src/interfaces/{students.ts => student.ts} (100%) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index feabb1e1..1a79c8b1 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,7 +1,7 @@ import { Request, Response } from 'express' import { getAssignment } from '../services/assignments'; -// typescript is annoywith with parameter forwarding from classes.ts +// typescript is annoywith with parameter forwarding from class.ts interface AssignmentParams { classid: string; id: string; diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index c8095162..65391781 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; import {getAllClasses, getClass, getClassStudents, getClassStudentsIds} from '../services/class'; -import { ClassDTO } from '../interfaces/classes'; +import { ClassDTO } from '../interfaces/class'; export async function getAllClassesHandler( req: Request, diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index c6973632..64822b4d 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; import { getAllStudents, getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; -import { ClassDTO } from '../interfaces/classes'; +import { ClassDTO } from '../interfaces/class'; // TODO: accept arguments (full, ...) // TODO: endpoints @@ -27,7 +27,7 @@ export async function getStudentHandler( try { const username = req.params.id; const student = await getStudent(username); - + if (!student) { res.status(404).json({ error: "Student not found" }); return; @@ -72,4 +72,4 @@ export async function getStudentClassesHandler ( console.error('Error fetching learning objects:', error); res.status(500).json({ error: 'Internal server error' }); } -} \ No newline at end of file +} diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index 6f363c20..2ef63b65 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -9,8 +9,8 @@ import { getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher } from '../services/teachers.js'; import {TeacherDTO} from "../interfaces/teacher"; -import {ClassDTO} from "../interfaces/classes"; -import {StudentDTO} from "../interfaces/students"; +import {ClassDTO} from "../interfaces/class"; +import {StudentDTO} from "../interfaces/student"; export async function getTeacherHandler(req: Request, res: Response): Promise { try { diff --git a/backend/src/interfaces/assignments.ts b/backend/src/interfaces/assignment.ts similarity index 95% rename from backend/src/interfaces/assignments.ts rename to backend/src/interfaces/assignment.ts index a3c3c4cc..59242920 100644 --- a/backend/src/interfaces/assignments.ts +++ b/backend/src/interfaces/assignment.ts @@ -1,6 +1,6 @@ import { Assignment } from "../entities/assignments/assignment.entity"; import { Class } from "../entities/classes/class.entity"; -import { GroupDTO } from "./groups"; +import { GroupDTO } from "./group"; export interface AssignmentDTO { id: number, @@ -22,4 +22,4 @@ export function mapToAssignmentDTO(assignment: Assignment, cls: Class): Assignme language: assignment.learningPathLanguage, //groups: assignment.groups.map(mapToGroupDTO), }; -} \ No newline at end of file +} diff --git a/backend/src/interfaces/classes.ts b/backend/src/interfaces/class.ts similarity index 100% rename from backend/src/interfaces/classes.ts rename to backend/src/interfaces/class.ts diff --git a/backend/src/interfaces/groups.ts b/backend/src/interfaces/group.ts similarity index 100% rename from backend/src/interfaces/groups.ts rename to backend/src/interfaces/group.ts diff --git a/backend/src/interfaces/students.ts b/backend/src/interfaces/student.ts similarity index 100% rename from backend/src/interfaces/students.ts rename to backend/src/interfaces/student.ts diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index ab76f6a8..48c6b883 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -1,5 +1,5 @@ import { getAssignmentRepository, getClassRepository } from "../data/repositories"; -import { AssignmentDTO, mapToAssignmentDTO } from "../interfaces/assignments"; +import { AssignmentDTO, mapToAssignmentDTO } from "../interfaces/assignment"; export async function getAssignment(classid: string, id: number): Promise { const classRepository = getClassRepository(); @@ -8,7 +8,7 @@ export async function getAssignment(classid: string, id: number): Promise { const classRepository = getClassRepository(); diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index a69cab85..5def5119 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,8 +1,8 @@ import { getClassRepository, getStudentRepository } from "../data/repositories"; import { Class } from "../entities/classes/class.entity"; import { Student } from "../entities/users/student.entity"; -import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; -import { StudentDTO, mapToStudentDTO } from "../interfaces/students"; +import { ClassDTO, mapToClassDTO } from "../interfaces/class"; +import { StudentDTO, mapToStudentDTO } from "../interfaces/student"; export async function getAllStudents(): Promise { @@ -16,8 +16,8 @@ export async function getStudent(username: string): Promise { const studentRepository = getStudentRepository(); const student = await studentRepository.findByUsername(username); - if (!student) { - return null; + if (!student) { + return null; } return mapToStudentDTO(student); diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 39ee3997..8382e4b3 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -1,9 +1,9 @@ import {getClassRepository, getTeacherRepository} from "../data/repositories.js"; import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; import { Teacher } from "../entities/users/teacher.entity"; -import {ClassDTO, mapToClassDTO} from "../interfaces/classes"; +import {ClassDTO, mapToClassDTO} from "../interfaces/class"; import {getClassStudents, getClassStudentsIds} from "./class"; -import {StudentDTO} from "../interfaces/students"; +import {StudentDTO} from "../interfaces/student"; async function fetchAllTeachers(): Promise { From 16b73b9e182bc5b6778fa28bc94ef70de3ac397a Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Sat, 8 Mar 2025 10:19:22 +0100 Subject: [PATCH 15/49] feat: question-teacher route --- backend/src/controllers/teachers.ts | 31 ++++++++++-- .../content/learning-object-repository.ts | 8 ++++ .../src/data/questions/question-repository.ts | 14 ++++++ backend/src/interfaces/question.ts | 41 ++++++++++++++++ backend/src/routes/teachers.ts | 19 +------- backend/src/services/teachers.ts | 47 ++++++++++++++++++- 6 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 backend/src/interfaces/question.ts diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index 2ef63b65..d3b6a4db 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -2,15 +2,16 @@ import { Request, Response } from 'express'; import { createTeacher, deleteTeacher, - fetchTeacherByUsername, + getTeacherByUsername, getClassesByTeacher, getClassIdsByTeacher, getAllTeachers, - getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher + getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher, getQuestionsByTeacher, getQuestionIdsByTeacher } from '../services/teachers.js'; import {TeacherDTO} from "../interfaces/teacher"; import {ClassDTO} from "../interfaces/class"; import {StudentDTO} from "../interfaces/student"; +import {QuestionDTO, QuestionId} from "../interfaces/question"; export async function getTeacherHandler(req: Request, res: Response): Promise { try { @@ -18,7 +19,7 @@ export async function getTeacherHandler(req: Request, res: Response): Promise { + try { + const username = req.params.username as string; + const full = req.query.full === 'true'; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + let questions: QuestionDTO[] | QuestionId[]; + + if (full) questions = await getQuestionsByTeacher(username); + else questions = await getQuestionIdsByTeacher(username); + + res.status(201).json(questions); + } catch (error) { + console.error('Error fetching questions by teacher:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + + diff --git a/backend/src/data/content/learning-object-repository.ts b/backend/src/data/content/learning-object-repository.ts index 5d30b956..d8b07943 100644 --- a/backend/src/data/content/learning-object-repository.ts +++ b/backend/src/data/content/learning-object-repository.ts @@ -1,6 +1,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { LearningObject } from '../../entities/content/learning-object.entity.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; +import {Teacher} from "../../entities/users/teacher.entity"; export class LearningObjectRepository extends DwengoEntityRepository { public findByIdentifier( @@ -13,4 +14,11 @@ export class LearningObjectRepository extends DwengoEntityRepository { + return this.find( + { admins: teacher }, + { populate: ['admins'] } // Make sure to load admin relations + ); + } } diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index 517305f1..05430ddd 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -2,6 +2,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Question } from '../../entities/questions/question.entity.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; import { Student } from '../../entities/users/student.entity.js'; +import {LearningObject} from "../../entities/content/learning-object.entity"; export class QuestionRepository extends DwengoEntityRepository { public createQuestion(question: { @@ -42,4 +43,17 @@ export class QuestionRepository extends DwengoEntityRepository { sequenceNumber: sequenceNumber, }); } + + public async findAllByLearningObjects(learningObjects: LearningObject[]): Promise { + const objectIdentifiers = learningObjects.map(lo => ({ + learningObjectHruid: lo.hruid, + learningObjectLanguage: lo.language, + learningObjectVersion: lo.version + })); + + return this.findAll({ + where: { $or: objectIdentifiers }, + orderBy: { timestamp: 'ASC' }, + }); + } } diff --git a/backend/src/interfaces/question.ts b/backend/src/interfaces/question.ts new file mode 100644 index 00000000..1a8c914a --- /dev/null +++ b/backend/src/interfaces/question.ts @@ -0,0 +1,41 @@ +import {Question} from "../entities/questions/question.entity"; +import {Enum, PrimaryKey} from "@mikro-orm/core"; +import {Language} from "../entities/content/language"; + +export interface QuestionDTO { + learningObjectHruid: string; + learningObjectLanguage: string; + learningObjectVersion: string; + sequenceNumber: number; + authorUsername: string; + timestamp: string; + content: string; + endpoints?: { + classes: string; + questions: string; + invitations: string; + groups: string; + }; +} + +/** + * Convert a Question entity to a DTO format. + */ +export function mapToQuestionDTO(question: Question): QuestionDTO { + return { + learningObjectHruid: question.learningObjectHruid, + learningObjectLanguage: question.learningObjectLanguage, + learningObjectVersion: question.learningObjectVersion, + sequenceNumber: question.sequenceNumber, + authorUsername: question.author.username, + timestamp: question.timestamp.toISOString(), + content: question.content, + }; +} + +export interface QuestionId { + learningObjectHruid: string, + learningObjectLanguage: Language, + learningObjectVersion: string, + sequenceNumber: number +} diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index 338ac0b8..2a29897b 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -3,7 +3,7 @@ import { createTeacherHandler, deleteTeacherHandler, getTeacherClassHandler, - getTeacherHandler, getTeacherStudentHandler + getTeacherHandler, getTeacherQuestionHandler, getTeacherStudentHandler } from "../controllers/teachers.js"; const router = express.Router(); @@ -18,14 +18,7 @@ router.get('/:username/classes', getTeacherClassHandler); router.get('/:username/students', getTeacherStudentHandler); -// the questions students asked a teacher -router.get('/:id/questions', (req, res) => { - res.json({ - questions: [ - '0' - ], - }); -}); +router.get('/:username/questions', getTeacherQuestionHandler); // invitations to other classes a teacher received router.get('/:id/invitations', (req, res) => { @@ -36,14 +29,6 @@ router.get('/:id/invitations', (req, res) => { }); }); -// a list with ids of classes a teacher is in -router.get('/:id/classes', (req, res) => { - res.json({ - classes: [ - '0' - ], - }); -}); export default router diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 8382e4b3..4b8affc5 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -1,9 +1,15 @@ -import {getClassRepository, getTeacherRepository} from "../data/repositories.js"; +import { + getClassRepository, + getLearningObjectRepository, + getQuestionRepository, + getTeacherRepository +} from "../data/repositories.js"; import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; import { Teacher } from "../entities/users/teacher.entity"; import {ClassDTO, mapToClassDTO} from "../interfaces/class"; import {getClassStudents, getClassStudentsIds} from "./class"; import {StudentDTO} from "../interfaces/student"; +import {mapToQuestionDTO, QuestionDTO, QuestionId} from "../interfaces/question"; async function fetchAllTeachers(): Promise { @@ -29,7 +35,7 @@ export async function createTeacher(teacherData: TeacherDTO): Promise { return newTeacher; } -export async function fetchTeacherByUsername(username: string): Promise { +export async function getTeacherByUsername(username: string): Promise { const teacherRepository = getTeacherRepository(); const teacher = await teacherRepository.findByUsername(username); @@ -84,5 +90,42 @@ export async function getStudentIdsByTeacher(): Promise { return await fetchStudentsByTeacher(username).map((student) => student.username); } +async function fetchTeacherQuestions(username: string): Promise { + const learningObjectRepository = getLearningObjectRepository(); + const questionRepository = getQuestionRepository(); + + const teacher = getTeacherByUsername(username); + if (!teacher) { + throw new Error(`Teacher with username '${username}' not found.`); + } + + // Find all learning objects that this teacher manages + const learningObjects = await learningObjectRepository.findAllByTeacher(teacher); + + // Fetch all questions related to these learning objects + const questions = await questionRepository.findAllByLearningObjects(learningObjects); + + return questions.map(mapToQuestionDTO); +} + +export async function getQuestionsByTeacher(username: string): Promise { + return await fetchTeacherQuestions(username); +} + +export async function getQuestionIdsByTeacher(username: string): Promise { + const questions = await fetchTeacherQuestions(username); + + return questions.map((question) => ({ + learningObjectHruid: question.learningObjectHruid, + learningObjectLanguage: question.learningObjectLanguage, + learningObjectVersion: question.learningObjectVersion, + sequenceNumber: question.sequenceNumber + })); +} + + + + + From baf43e91dec816792911f993ea3107fa6c217ae5 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Sat, 8 Mar 2025 20:16:57 +0100 Subject: [PATCH 16/49] feat: teacher invitation databank api verbinding aangemaakt, bug in data repo waar teacher invitation repo niet juist werd teruggegeven gefixt --- backend/src/controllers/classes.ts | 16 +++++++++++- backend/src/data/repositories.ts | 2 +- backend/src/interfaces/teacher-invitation.ts | 25 ++++++++++++++++++ backend/src/interfaces/teacher.ts | 23 +++++++++++++++++ backend/src/routes/class.ts | 10 ++------ backend/src/services/class.ts | 27 +++++++++++++++++++- 6 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 backend/src/interfaces/teacher-invitation.ts create mode 100644 backend/src/interfaces/teacher.ts diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index ee932734..d7580d62 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import { getAllClasses, getClass, getClassStudents } from '../services/class'; +import { getAllClasses, getClass, getClassStudents, getClassTeacherInvitations } from '../services/class'; import { ClassDTO } from '../interfaces/classes'; export async function getAllClassesHandler( @@ -53,4 +53,18 @@ export async function getClassStudentsHandler( res.json({ students: students, }); +} + +export async function getTeacherInvitationsHandler( + req: Request, + res: Response, +): Promise { + const classId = req.params.id; + const full = req.query.full === "true"; // TODO: not implemented yet + + const invitations = await getClassTeacherInvitations(classId, full); + + res.json({ + invitations: invitations, + }); } \ No newline at end of file diff --git a/backend/src/data/repositories.ts b/backend/src/data/repositories.ts index 843eb1ac..35ad26cd 100644 --- a/backend/src/data/repositories.ts +++ b/backend/src/data/repositories.ts @@ -80,7 +80,7 @@ export const getClassJoinRequestRepository = repositoryGetter< export const getTeacherInvitationRepository = repositoryGetter< TeacherInvitation, TeacherInvitationRepository ->(TeacherInvitationRepository); +>(TeacherInvitation); /* Assignments */ export const getAssignmentRepository = repositoryGetter< diff --git a/backend/src/interfaces/teacher-invitation.ts b/backend/src/interfaces/teacher-invitation.ts new file mode 100644 index 00000000..c563968b --- /dev/null +++ b/backend/src/interfaces/teacher-invitation.ts @@ -0,0 +1,25 @@ +import { TeacherInvitation } from "../entities/classes/teacher-invitation.entity"; +import { ClassDTO, mapToClassDTO } from "./classes"; +import { mapToTeacherDTO, TeacherDTO } from "./teacher"; + +export interface TeacherInvitationDTO { + sender: string | TeacherDTO, + receiver: string | TeacherDTO, + class: string | ClassDTO, +} + +export function mapToTeacherInvitationDTO(invitation: TeacherInvitation): TeacherInvitationDTO { + return { + sender: mapToTeacherDTO(invitation.sender), + receiver: mapToTeacherDTO(invitation.receiver), + class: mapToClassDTO(invitation.class), + }; +} + +export function mapToTeacherInvitationDTOIds(invitation: TeacherInvitation): TeacherInvitationDTO { + return { + sender: invitation.sender.username, + receiver: invitation.receiver.username, + class: invitation.class.classId, + }; +} \ No newline at end of file diff --git a/backend/src/interfaces/teacher.ts b/backend/src/interfaces/teacher.ts new file mode 100644 index 00000000..5aee089c --- /dev/null +++ b/backend/src/interfaces/teacher.ts @@ -0,0 +1,23 @@ +import { Teacher } from "../entities/users/teacher.entity"; + +export interface TeacherDTO { + id: string; + username: string; + firstName: string; + lastName: string; + endpoints?: { + classes: string; + questions: string; + invitations: string; + groups: string; + }; +} + +export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { + return { + id: teacher.username, + username: teacher.username, + firstName: teacher.firstName, + lastName: teacher.lastName, + }; +} \ No newline at end of file diff --git a/backend/src/routes/class.ts b/backend/src/routes/class.ts index bc502fb8..369e6ff4 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/class.ts @@ -1,5 +1,5 @@ import express from 'express' -import { getAllClassesHandler, getClassHandler, getClassStudentsHandler } from '../controllers/classes'; +import { getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../controllers/classes'; import assignmentRouter from './assignment.js'; const router = express.Router(); @@ -10,13 +10,7 @@ router.get('/', getAllClassesHandler); // information about an class with id 'id' router.get('/:id', getClassHandler); -router.get('/:id/invitations', (req, res) => { - res.json({ - invitations: [ - '0' - ], - }); -}) +router.get('/:id/teacher-invitations', getTeacherInvitationsHandler); router.get('/:id/students', getClassStudentsHandler); diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 89628404..b009b66c 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -1,7 +1,8 @@ -import { getClassRepository } from "../data/repositories"; +import { getClassRepository, getTeacherInvitationRepository } from "../data/repositories"; import { Class } from "../entities/classes/class.entity"; import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; import { mapToStudentDTO, StudentDTO } from "../interfaces/students"; +import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from "../interfaces/teacher-invitation"; export async function getAllClasses(full: boolean): Promise { const classRepository = getClassRepository(); @@ -41,4 +42,28 @@ export async function getClassStudents(classId: string, full: boolean): Promise< } else { return cls.students.map((student) => student.username); } +} + +export async function getClassTeacherInvitations(classId: string, full: boolean): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classId); + + if (!cls) { + return []; + } + + const teacherInvitationRepository = getTeacherInvitationRepository(); + const invitations = await teacherInvitationRepository.findAllInvitationsForClass(cls); + + console.log(invitations); + + if (!invitations) { + return []; + } + + if (full) { + return invitations.map(mapToTeacherInvitationDTO); + } + + return invitations.map(mapToTeacherInvitationDTOIds); } \ No newline at end of file From 3f62ab70e1d77ad8c3718e553d923c51c5388213 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Sat, 8 Mar 2025 21:49:29 +0100 Subject: [PATCH 17/49] feat: group verbinding tussen databank en api aangemaakt --- backend/src/controllers/groups.ts | 34 ++++++++++++++++++ .../src/data/assignments/group-repository.ts | 7 ++-- backend/src/interfaces/groups.ts | 22 ++++++++++++ backend/src/routes/assignment.ts | 14 +++----- backend/src/routes/group.ts | 15 ++------ backend/src/services/groups.ts | 36 +++++++++++++++++++ 6 files changed, 104 insertions(+), 24 deletions(-) create mode 100644 backend/src/controllers/groups.ts create mode 100644 backend/src/services/groups.ts diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts new file mode 100644 index 00000000..7ca6617d --- /dev/null +++ b/backend/src/controllers/groups.ts @@ -0,0 +1,34 @@ +import { Request, Response } from 'express'; +import { getGroup } from '../services/groups'; + +// typescript is annoywith with parameter forwarding from class.ts +interface GroupParams { + classid: string; + assignmentid: string; + groupid: string; +} + +export async function getGroupHandler( + req: Request, + res: Response, +): Promise { + const classId = req.params.classid; + const full = req.query.full === "true"; + const assignmentId = +req.params.assignmentid; + + if (isNaN(assignmentId)) { + res.status(400).json({ error: "Assignment id must be a number" }); + return; + } + + const groupId = +req.params.groupid; + + if (isNaN(groupId)) { + res.status(400).json({ error: "Group id must be a number" }); + return; + } + + const group = await getGroup(classId, assignmentId, groupId, full); + + res.json(group); +} \ No newline at end of file diff --git a/backend/src/data/assignments/group-repository.ts b/backend/src/data/assignments/group-repository.ts index ff8ca507..3992e113 100644 --- a/backend/src/data/assignments/group-repository.ts +++ b/backend/src/data/assignments/group-repository.ts @@ -7,10 +7,13 @@ export class GroupRepository extends DwengoEntityRepository { assignment: Assignment, groupNumber: number ): Promise { - return this.findOne({ + return this.findOne( + { assignment: assignment, groupNumber: groupNumber, - }); + }, + { populate: ["members"] }, + ); } public findAllGroupsForAssignment( assignment: Assignment diff --git a/backend/src/interfaces/groups.ts b/backend/src/interfaces/groups.ts index 6056a906..fe78cc69 100644 --- a/backend/src/interfaces/groups.ts +++ b/backend/src/interfaces/groups.ts @@ -1,3 +1,25 @@ +import { Group } from "../entities/assignments/group.entity"; +import { AssignmentDTO, mapToAssignmentDTO } from "./assignments"; +import { mapToStudentDTO, StudentDTO } from "./students"; + export interface GroupDTO { + assignment: number | AssignmentDTO, groupNumber: number, + members: string[] | StudentDTO[], +}; + +export function mapToGroupDTO(group: Group): GroupDTO { + return { + assignment: mapToAssignmentDTO(group.assignment, group.assignment.within), + groupNumber: group.groupNumber, + members: group.members.map(mapToStudentDTO), + } +} + +export function mapToGroupDTOId(group: Group): GroupDTO { + return { + assignment: group.assignment.id, + groupNumber: group.groupNumber, + members: group.members.map(member => member.username), + } } \ No newline at end of file diff --git a/backend/src/routes/assignment.ts b/backend/src/routes/assignment.ts index e9c91160..35b4b986 100644 --- a/backend/src/routes/assignment.ts +++ b/backend/src/routes/assignment.ts @@ -1,9 +1,9 @@ import express from 'express' import { getAssignmentHandler } from '../controllers/assignments'; +import groupRouter from './group.js'; + const router = express.Router({ mergeParams: true }); - - // root endpoint used to search objects router.get('/', (req, res) => { res.json({ @@ -25,14 +25,6 @@ router.get('/:id/submissions', (req, res) => { }); }); -router.get('/:id/groups', (req, res) => { - res.json({ - groups: [ - '0' - ], - }); -}); - router.get('/:id/questions', (req, res) => { res.json({ questions: [ @@ -41,4 +33,6 @@ router.get('/:id/questions', (req, res) => { }); }); +router.use('/:assignmentid/groups', groupRouter); + export default router \ No newline at end of file diff --git a/backend/src/routes/group.ts b/backend/src/routes/group.ts index e55dddd1..436e228a 100644 --- a/backend/src/routes/group.ts +++ b/backend/src/routes/group.ts @@ -1,5 +1,6 @@ import express from 'express' -const router = express.Router(); +import { getGroupHandler } from '../controllers/groups'; +const router = express.Router({ mergeParams: true }); // root endpoint used to search objects router.get('/', (req, res) => { @@ -12,17 +13,7 @@ router.get('/', (req, res) => { }); // information about a group (members, ... [TODO DOC]) -router.get('/:id', (req, res) => { - res.json({ - id: req.params.id, - assignment: '0', - students: [ '0' ], - submissions: [ '0' ], - // reference to other endpoint - // should be less hardcoded - questions: `/group/${req.params.id}/question`, - }); -}) +router.get('/:groupid', getGroupHandler); // the list of questions a group has made router.get('/:id/question', (req, res) => { diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts new file mode 100644 index 00000000..c1b6cf33 --- /dev/null +++ b/backend/src/services/groups.ts @@ -0,0 +1,36 @@ +import { getAssignmentRepository, getClassRepository, getGroupRepository } from "../data/repositories"; +import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from "../interfaces/groups"; + +export async function getGroup( + classId: string, + assignmentNumber: number, + groupNumber: number, + full: boolean, +): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classId); + + if (!cls) { + return null; + } + + const assignmentRepository = getAssignmentRepository(); + const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); + + if (!assignment) { + return null; + } + + const groupRepository = getGroupRepository(); + const group = await groupRepository.findByAssignmentAndGroupNumber(assignment, groupNumber); + + if (!group) { + return null; + } + + if (full) { + return mapToGroupDTO(group); + } + + return mapToGroupDTOId(group); +} \ No newline at end of file From 7e051d412a92bb8113d76c792f8eb984b342ad07 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Sun, 9 Mar 2025 13:39:53 +0100 Subject: [PATCH 18/49] feat: endpoint voor alle groepen van een assignment geimplementeerd --- backend/src/controllers/groups.ts | 27 ++++++++++++++-- .../src/data/assignments/group-repository.ts | 6 +++- backend/src/routes/group.ts | 11 ++----- backend/src/services/groups.ts | 31 +++++++++++++++++++ 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 7ca6617d..1c523744 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -1,11 +1,11 @@ import { Request, Response } from 'express'; -import { getGroup } from '../services/groups'; +import { getAllGroups, getGroup } from '../services/groups'; // typescript is annoywith with parameter forwarding from class.ts interface GroupParams { classid: string; assignmentid: string; - groupid: string; + groupid?: string; } export async function getGroupHandler( @@ -21,7 +21,7 @@ export async function getGroupHandler( return; } - const groupId = +req.params.groupid; + const groupId = +req.params.groupid!; // can't be undefined if (isNaN(groupId)) { res.status(400).json({ error: "Group id must be a number" }); @@ -31,4 +31,25 @@ export async function getGroupHandler( const group = await getGroup(classId, assignmentId, groupId, full); res.json(group); +} + +export async function getAllGroupsHandler( + req: Request, + res: Response, +): Promise { + const classId = req.params.classid; + const full = req.query.full === "true"; + + const assignmentId = +req.params.assignmentid; + + if (isNaN(assignmentId)) { + res.status(400).json({ error: "Assignment id must be a number" }); + return; + } + + const groups = await getAllGroups(classId, assignmentId, full); + + res.json({ + groups: groups, + }); } \ No newline at end of file diff --git a/backend/src/data/assignments/group-repository.ts b/backend/src/data/assignments/group-repository.ts index 3992e113..c8770eb5 100644 --- a/backend/src/data/assignments/group-repository.ts +++ b/backend/src/data/assignments/group-repository.ts @@ -18,7 +18,11 @@ export class GroupRepository extends DwengoEntityRepository { public findAllGroupsForAssignment( assignment: Assignment ): Promise { - return this.findAll({ where: { assignment: assignment } }); + return this.findAll({ + where: { assignment: assignment }, + populate: ["members"] + }, + ); } public deleteByAssignmentAndGroupNumber( assignment: Assignment, diff --git a/backend/src/routes/group.ts b/backend/src/routes/group.ts index 436e228a..a8d4dbe5 100644 --- a/backend/src/routes/group.ts +++ b/backend/src/routes/group.ts @@ -1,16 +1,9 @@ import express from 'express' -import { getGroupHandler } from '../controllers/groups'; +import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups'; const router = express.Router({ mergeParams: true }); // root endpoint used to search objects -router.get('/', (req, res) => { - res.json({ - groups: [ - '0', - '1', - ] - }); -}); +router.get('/', getAllGroupsHandler); // information about a group (members, ... [TODO DOC]) router.get('/:groupid', getGroupHandler); diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index c1b6cf33..c9a4024e 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -33,4 +33,35 @@ export async function getGroup( } return mapToGroupDTOId(group); +} + +export async function getAllGroups( + classId: string, + assignmentNumber: number, + full: boolean, +): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classId); + + if (!cls) { + return []; + } + + const assignmentRepository = getAssignmentRepository(); + const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); + + if (!assignment) { + return []; + } + + const groupRepository = getGroupRepository(); + const groups = await groupRepository.findAllGroupsForAssignment(assignment); + + if (full) { + console.log('full'); + console.log(groups); + return groups.map(mapToGroupDTO); + } + + return groups.map(mapToGroupDTOId); } \ No newline at end of file From e0a5596994770305c79aa3859d696f8b7e9d4140 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Sun, 9 Mar 2025 15:31:10 +0100 Subject: [PATCH 19/49] feat: alle assignments en student's assignments geimplementeerd --- backend/src/controllers/assignments.ts | 18 ++++++++++++++++-- backend/src/controllers/students.ts | 20 ++++++++++++++++++++ backend/src/interfaces/assignments.ts | 22 +++++++++++++++++----- backend/src/routes/assignment.ts | 11 ++--------- backend/src/routes/student.ts | 8 ++------ backend/src/services/assignments.ts | 22 ++++++++++++++++++++-- 6 files changed, 77 insertions(+), 24 deletions(-) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 775a60df..78d11336 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,12 +1,26 @@ import { Request, Response } from 'express' -import { getAssignment } from '../services/assignments'; +import { getAllAssignments, getAssignment } from '../services/assignments'; -// typescript is annoywith with parameter forwarding from class.ts +// typescript is annoy with with parameter forwarding from class.ts interface AssignmentParams { classid: string; id: string; } +export async function getAllAssignmentsHandler( + req: Request, + res: Response, +): Promise { + const classid = req.params.classid; + const full = req.query.full === 'true'; + + const assignments = await getAllAssignments(classid, full); + + res.json({ + assignments: assignments, + }); +} + export async function getAssignmentHandler( req: Request, res: Response, diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index c6973632..68a5fc76 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,6 +1,7 @@ import { Request, Response } from 'express'; import { getAllStudents, getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; import { ClassDTO } from '../interfaces/classes'; +import { getAllAssignments } from '../services/assignments'; // TODO: accept arguments (full, ...) // TODO: endpoints @@ -72,4 +73,23 @@ export async function getStudentClassesHandler ( console.error('Error fetching learning objects:', error); res.status(500).json({ error: 'Internal server error' }); } +} + +// Might not be fully correct depending on if +// a class has an assignment, that all students +// have this assignment. +export async function getStudentAssignmentsHandler( + req: Request, + res: Response, +): Promise { + const full = req.query.full === 'true'; + const username = req.params.id; + + const classes = await getStudentClasses(username); + + const assignments = (await Promise.all(classes.map(async cls => await getAllAssignments(cls.id, full)))).flat(); + + res.json({ + assignments: assignments + }); } \ No newline at end of file diff --git a/backend/src/interfaces/assignments.ts b/backend/src/interfaces/assignments.ts index a3c3c4cc..7fabece5 100644 --- a/backend/src/interfaces/assignments.ts +++ b/backend/src/interfaces/assignments.ts @@ -1,6 +1,6 @@ import { Assignment } from "../entities/assignments/assignment.entity"; import { Class } from "../entities/classes/class.entity"; -import { GroupDTO } from "./groups"; +import { GroupDTO, mapToGroupDTO } from "./groups"; export interface AssignmentDTO { id: number, @@ -9,17 +9,29 @@ export interface AssignmentDTO { description: string, learningPath: string, language: string, - groups?: GroupDTO[], // TODO + groups?: GroupDTO[] | string[], // TODO } -export function mapToAssignmentDTO(assignment: Assignment, cls: Class): AssignmentDTO { +export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { return { id: assignment.id, - class: cls.classId, + class: assignment.within.classId, title: assignment.title, description: assignment.description, learningPath: assignment.learningPathHruid, language: assignment.learningPathLanguage, - //groups: assignment.groups.map(mapToGroupDTO), + // groups: assignment.groups.map(group => group.groupNumber), + } +} + +export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO { + return { + id: assignment.id, + class: assignment.within.classId, + title: assignment.title, + description: assignment.description, + learningPath: assignment.learningPathHruid, + language: assignment.learningPathLanguage, + // groups: assignment.groups.map(mapToGroupDTO), }; } \ No newline at end of file diff --git a/backend/src/routes/assignment.ts b/backend/src/routes/assignment.ts index 35b4b986..d6965c49 100644 --- a/backend/src/routes/assignment.ts +++ b/backend/src/routes/assignment.ts @@ -1,18 +1,11 @@ import express from 'express' -import { getAssignmentHandler } from '../controllers/assignments'; +import { getAllAssignmentsHandler, getAssignmentHandler } from '../controllers/assignments'; import groupRouter from './group.js'; const router = express.Router({ mergeParams: true }); // root endpoint used to search objects -router.get('/', (req, res) => { - res.json({ - assignments: [ - '0', - '1', - ] - }); -}); +router.get('/', getAllAssignmentsHandler); // information about an assignment with id 'id' router.get('/:id', getAssignmentHandler); diff --git a/backend/src/routes/student.ts b/backend/src/routes/student.ts index ca74d2f7..bc806b4e 100644 --- a/backend/src/routes/student.ts +++ b/backend/src/routes/student.ts @@ -1,5 +1,5 @@ import express from 'express' -import { getAllStudentsHandler, getStudentClassesHandler, getStudentHandler } from '../controllers/students'; +import { getAllStudentsHandler, getStudentAssignmentsHandler, getStudentClassesHandler, getStudentHandler } from '../controllers/students'; const router = express.Router(); // root endpoint used to search objects @@ -20,11 +20,7 @@ router.get('/:id/submissions', (req, res) => { // the list of assignments a student has -router.get('/:id/assignments', (req, res) => { - res.json({ - assignments: [ '0' ], - }); -}) +router.get('/:id/assignments', getStudentAssignmentsHandler); // the list of groups a student is in router.get('/:id/groups', (req, res) => { diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index ab76f6a8..e0804750 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -1,5 +1,23 @@ import { getAssignmentRepository, getClassRepository } from "../data/repositories"; -import { AssignmentDTO, mapToAssignmentDTO } from "../interfaces/assignments"; +import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId } from "../interfaces/assignments"; + +export async function getAllAssignments(classid: string, full: boolean): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classid); + + if (!cls) { + return []; + } + + const assignmentRepository = getAssignmentRepository(); + const assignments = await assignmentRepository.findAllAssignmentsInClass(cls); + + if (full) { + return assignments.map(mapToAssignmentDTO); + } + + return assignments.map(mapToAssignmentDTOId); +} export async function getAssignment(classid: string, id: number): Promise { const classRepository = getClassRepository(); @@ -16,5 +34,5 @@ export async function getAssignment(classid: string, id: number): Promise Date: Sun, 9 Mar 2025 20:18:11 +0100 Subject: [PATCH 20/49] feat: add, delete student route met user logic + .js in files --- backend/src/app.ts | 1 + backend/src/controllers/assignments.ts | 4 +- backend/src/controllers/classes.ts | 7 +- backend/src/controllers/groups.ts | 4 +- backend/src/controllers/students.ts | 69 +++++------- backend/src/controllers/users.ts | 106 ++++++++++++++++++ backend/src/data/repositories.ts | 2 +- backend/src/data/users/student-repository.ts | 11 +- backend/src/data/users/teacher-repository.ts | 11 +- backend/src/data/users/user-repository.ts | 8 +- .../content/learning-object.entity.ts | 18 +-- backend/src/entities/users/student.entity.ts | 8 -- backend/src/interfaces/assignments.ts | 7 +- backend/src/interfaces/classes.ts | 2 +- backend/src/interfaces/groups.ts | 10 +- backend/src/interfaces/students.ts | 13 ++- backend/src/interfaces/teacher-invitation.ts | 8 +- backend/src/interfaces/teacher.ts | 4 +- backend/src/interfaces/user.ts | 30 +++++ backend/src/routes/assignment.ts | 4 +- backend/src/routes/class.ts | 4 +- backend/src/routes/group.ts | 4 +- backend/src/routes/student.ts | 22 +++- backend/src/services/assignments.ts | 10 +- backend/src/services/class.ts | 13 +-- backend/src/services/groups.ts | 10 +- backend/src/services/students.ts | 29 ++--- backend/src/services/users.ts | 39 +++++++ backend/src/util/translationHelper.ts | 2 +- 29 files changed, 301 insertions(+), 159 deletions(-) create mode 100644 backend/src/controllers/users.ts create mode 100644 backend/src/interfaces/user.ts create mode 100644 backend/src/services/users.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index e4da44e7..8f01dea6 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -16,6 +16,7 @@ import loginRouter from './routes/login.js'; const app: Express = express(); const port: string | number = getNumericEnvVar(EnvVars.Port); +app.use(express.json()); // TODO Replace with Express routes app.get('/', (_, res: Response) => { diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 78d11336..ab0f951f 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express' -import { getAllAssignments, getAssignment } from '../services/assignments'; +import { getAllAssignments, getAssignment } from '../services/assignments.js'; // typescript is annoy with with parameter forwarding from class.ts interface AssignmentParams { @@ -41,4 +41,4 @@ export async function getAssignmentHandler( } res.json(assignment); -} \ No newline at end of file +} diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index d7580d62..9f8f4669 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,6 +1,5 @@ import { Request, Response } from 'express'; -import { getAllClasses, getClass, getClassStudents, getClassTeacherInvitations } from '../services/class'; -import { ClassDTO } from '../interfaces/classes'; +import { getAllClasses, getClass, getClassStudents, getClassTeacherInvitations } from '../services/class.js'; export async function getAllClassesHandler( req: Request, @@ -61,10 +60,10 @@ export async function getTeacherInvitationsHandler( ): Promise { const classId = req.params.id; const full = req.query.full === "true"; // TODO: not implemented yet - + const invitations = await getClassTeacherInvitations(classId, full); res.json({ invitations: invitations, }); -} \ No newline at end of file +} diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 1c523744..d301c98d 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import { getAllGroups, getGroup } from '../services/groups'; +import { getAllGroups, getGroup } from '../services/groups.js'; // typescript is annoywith with parameter forwarding from class.ts interface GroupParams { @@ -52,4 +52,4 @@ export async function getAllGroupsHandler( res.json({ groups: groups, }); -} \ No newline at end of file +} diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 68a5fc76..b4fe7b47 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,53 +1,33 @@ import { Request, Response } from 'express'; -import { getAllStudents, getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; -import { ClassDTO } from '../interfaces/classes'; -import { getAllAssignments } from '../services/assignments'; +import { + getStudentClasses, + getStudentClassIds, + StudentService +} from '../services/students.js'; +import { ClassDTO } from '../interfaces/classes.js'; +import { getAllAssignments } from '../services/assignments.js'; +import {createUserHandler, deleteUserHandler, getAllUsersHandler, getUserHandler} from "./users.js"; +import { Student } from "../entities/users/student.entity.js"; // TODO: accept arguments (full, ...) // TODO: endpoints -export async function getAllStudentsHandler ( - req: Request, - res: Response, -): Promise { - try { - const students = await getAllStudents(); - - res.json({ - students: students - }); - } catch (error) { - console.error('Error fetching learning objects:', error); - res.status(500).json({ error: 'Internal server error' }); - } +export async function getAllStudentsHandler (req: Request, res: Response): Promise { + await getAllUsersHandler(req, res, new StudentService()); } -export async function getStudentHandler( - req: Request, - res: Response, -): Promise { - try { - const username = req.params.id; - const student = await getStudent(username); - - if (!student) { - res.status(404).json({ error: "Student not found" }); - return; - } else { - student.endpoints = { - classes: `/student/${req.params.id}/classes`, - questions: `/student/${req.params.id}/submissions`, - invitations: `/student/${req.params.id}/assignments`, - groups: `/student/${req.params.id}/groups`, - } - res.json(student); - } - - } catch (error) { - console.error('Error fetching learning objects:', error); - res.status(500).json({ error: 'Internal server error' }); - } +export async function getStudentHandler(req: Request, res: Response): Promise { + await getUserHandler(req, res, new StudentService()); } +export async function createStudentHandler(req: Request, res: Response): Promise { + await createUserHandler(req, res, new StudentService(), Student); +} + +export async function deleteStudentHandler(req: Request, res: Response): Promise { + await deleteUserHandler(req, res, new StudentService()); +} + + export async function getStudentClassesHandler ( req: Request, res: Response, @@ -75,6 +55,7 @@ export async function getStudentClassesHandler ( } } +// TODO // Might not be fully correct depending on if // a class has an assignment, that all students // have this assignment. @@ -92,4 +73,6 @@ export async function getStudentAssignmentsHandler( res.json({ assignments: assignments }); -} \ No newline at end of file +} + + diff --git a/backend/src/controllers/users.ts b/backend/src/controllers/users.ts new file mode 100644 index 00000000..4b29617e --- /dev/null +++ b/backend/src/controllers/users.ts @@ -0,0 +1,106 @@ +import { Request, Response } from 'express'; +import { UserService } from "../services/users.js"; +import {UserDTO} from "../interfaces/user.js"; +import {User} from "../entities/users/user.entity.js"; + +export async function getAllUsersHandler( + req: Request, + res: Response, + service: UserService +): Promise { + try { + const full = req.query.full === 'true'; + + let users: UserDTO[] | string[] = full + ? await service.getAllUsers() + : await service.getAllUserIds(); + + if (!users){ + res.status(404).json({ error: `Users not found.` }); + return; + } + + res.status(201).json(users); + + } catch (error) { + console.error("❌ Error fetching users:", error); + res.status(500).json({ error: "Internal server error" }); + } +} + +export async function getUserHandler( + req: Request, + res: Response, + service: UserService +): Promise { + try { + const username = req.params.username as string; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + const user = await service.getUserByUsername(username); + + if (!user){ + res.status(404).json({ error: `User with username '${username}' not found.` }); + return; + } + + res.status(201).json(user); + + } catch (error) { + console.error("❌ Error fetching users:", error); + res.status(500).json({ error: "Internal server error" }); + } +} + +export async function createUserHandler( + req: Request, + res: Response, + service: UserService, + UserClass: new () => T +) { + try { + console.log("req", req) + const userData = req.body as UserDTO; + + if (!userData.username || !userData.firstName || !userData.lastName) { + res.status(400).json({ error: "Missing required fields: username, firstName, lastName" }); + return; + } + + const newUser = await service.createUser(userData, UserClass); + res.status(201).json(newUser); + } catch (error) { + console.error("❌ Error creating user:", error); + res.status(500).json({ error: "Internal server error" }); + } +} + +export async function deleteUserHandler ( + req: Request, + res: Response, + service: UserService +) { + try { + const username = req.params.username; + + if (!username) { + res.status(400).json({ error: "Missing required field: username" }); + return; + } + + const deletedUser = await service.deleteUser(username); + if (!deletedUser) { + res.status(404).json({ error: `User with username '${username}' not found.` }); + return; + } + + res.status(200).json(deletedUser); + } catch (error) { + console.error("❌ Error deleting user:", error); + res.status(500).json({ error: "Internal server error" }); + } +} diff --git a/backend/src/data/repositories.ts b/backend/src/data/repositories.ts index 35ad26cd..e65bb882 100644 --- a/backend/src/data/repositories.ts +++ b/backend/src/data/repositories.ts @@ -59,7 +59,7 @@ function repositoryGetter>( } /* Users */ -export const getUserRepository = repositoryGetter(User); +export const getUserRepository = repositoryGetter>(User); export const getStudentRepository = repositoryGetter< Student, StudentRepository diff --git a/backend/src/data/users/student-repository.ts b/backend/src/data/users/student-repository.ts index 1c3a6fae..c553aab8 100644 --- a/backend/src/data/users/student-repository.ts +++ b/backend/src/data/users/student-repository.ts @@ -1,11 +1,4 @@ -import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Student } from '../../entities/users/student.entity.js'; +import {UserRepository} from "./user-repository.js"; -export class StudentRepository extends DwengoEntityRepository { - public findByUsername(username: string): Promise { - return this.findOne({ username: username }); - } - public deleteByUsername(username: string): Promise { - return this.deleteWhere({ username: username }); - } -} +export class StudentRepository extends UserRepository {} diff --git a/backend/src/data/users/teacher-repository.ts b/backend/src/data/users/teacher-repository.ts index 704ef409..9940b4bd 100644 --- a/backend/src/data/users/teacher-repository.ts +++ b/backend/src/data/users/teacher-repository.ts @@ -1,11 +1,4 @@ -import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Teacher } from '../../entities/users/teacher.entity.js'; +import {UserRepository} from "./user-repository.js"; -export class TeacherRepository extends DwengoEntityRepository { - public findByUsername(username: string): Promise { - return this.findOne({ username: username }); - } - public deleteByUsername(username: string): Promise { - return this.deleteWhere({ username: username }); - } -} +export class TeacherRepository extends UserRepository {} diff --git a/backend/src/data/users/user-repository.ts b/backend/src/data/users/user-repository.ts index 7e2a42ad..21497b79 100644 --- a/backend/src/data/users/user-repository.ts +++ b/backend/src/data/users/user-repository.ts @@ -1,11 +1,11 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { User } from '../../entities/users/user.entity.js'; -export class UserRepository extends DwengoEntityRepository { - public findByUsername(username: string): Promise { - return this.findOne({ username: username }); +export class UserRepository extends DwengoEntityRepository { + public findByUsername(username: string): Promise { + return this.findOne({ username } as Partial); } public deleteByUsername(username: string): Promise { - return this.deleteWhere({ username: username }); + return this.deleteWhere({ username } as Partial); } } diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index 179a2f5f..78d4aa00 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -13,6 +13,15 @@ import { Attachment } from './attachment.entity.js'; import { Teacher } from '../users/teacher.entity.js'; import { LearningObjectRepository } from '../../data/content/learning-object-repository.js'; +@Embeddable() +export class ReturnValue { + @Property({ type: 'string' }) + callbackUrl!: string; + + @Property({ type: 'json' }) + callbackSchema!: string; +} + @Entity({ repository: () => LearningObjectRepository }) export class LearningObject { @PrimaryKey({ type: 'string' }) @@ -88,15 +97,6 @@ export class EducationalGoal { id!: string; } -@Embeddable() -export class ReturnValue { - @Property({ type: 'string' }) - callbackUrl!: string; - - @Property({ type: 'json' }) - callbackSchema!: string; -} - export enum ContentType { Markdown = 'text/markdown', Image = 'image/image', diff --git a/backend/src/entities/users/student.entity.ts b/backend/src/entities/users/student.entity.ts index dc791adc..401b1ed2 100644 --- a/backend/src/entities/users/student.entity.ts +++ b/backend/src/entities/users/student.entity.ts @@ -11,12 +11,4 @@ export class Student extends User { @ManyToMany(() => Group) groups!: Collection; - - constructor( - public username: string, - public firstName: string, - public lastName: string - ) { - super(); - } } diff --git a/backend/src/interfaces/assignments.ts b/backend/src/interfaces/assignments.ts index 7fabece5..146a0517 100644 --- a/backend/src/interfaces/assignments.ts +++ b/backend/src/interfaces/assignments.ts @@ -1,6 +1,5 @@ -import { Assignment } from "../entities/assignments/assignment.entity"; -import { Class } from "../entities/classes/class.entity"; -import { GroupDTO, mapToGroupDTO } from "./groups"; +import { Assignment } from "../entities/assignments/assignment.entity.js"; +import { GroupDTO, mapToGroupDTO } from "./groups.js"; export interface AssignmentDTO { id: number, @@ -34,4 +33,4 @@ export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO { language: assignment.learningPathLanguage, // groups: assignment.groups.map(mapToGroupDTO), }; -} \ No newline at end of file +} diff --git a/backend/src/interfaces/classes.ts b/backend/src/interfaces/classes.ts index 5c285446..0274d90c 100644 --- a/backend/src/interfaces/classes.ts +++ b/backend/src/interfaces/classes.ts @@ -1,4 +1,4 @@ -import { Class } from "../entities/classes/class.entity"; +import { Class } from "../entities/classes/class.entity.js"; export interface ClassDTO { id: string; diff --git a/backend/src/interfaces/groups.ts b/backend/src/interfaces/groups.ts index fe78cc69..c4c95baf 100644 --- a/backend/src/interfaces/groups.ts +++ b/backend/src/interfaces/groups.ts @@ -1,6 +1,6 @@ -import { Group } from "../entities/assignments/group.entity"; -import { AssignmentDTO, mapToAssignmentDTO } from "./assignments"; -import { mapToStudentDTO, StudentDTO } from "./students"; +import { Group } from "../entities/assignments/group.entity.js"; +import { AssignmentDTO, mapToAssignmentDTO } from "./assignments.js"; +import { mapToStudentDTO, StudentDTO } from "./students.js"; export interface GroupDTO { assignment: number | AssignmentDTO, @@ -10,7 +10,7 @@ export interface GroupDTO { export function mapToGroupDTO(group: Group): GroupDTO { return { - assignment: mapToAssignmentDTO(group.assignment, group.assignment.within), + assignment: mapToAssignmentDTO(group.assignment), // ERROR: , group.assignment.within), groupNumber: group.groupNumber, members: group.members.map(mapToStudentDTO), } @@ -22,4 +22,4 @@ export function mapToGroupDTOId(group: Group): GroupDTO { groupNumber: group.groupNumber, members: group.members.map(member => member.username), } -} \ No newline at end of file +} diff --git a/backend/src/interfaces/students.ts b/backend/src/interfaces/students.ts index e87e707d..c18461e8 100644 --- a/backend/src/interfaces/students.ts +++ b/backend/src/interfaces/students.ts @@ -1,4 +1,4 @@ -import { Student } from "../entities/users/student.entity"; +import { Student } from "../entities/users/student.entity.js"; export interface StudentDTO { id: string; @@ -20,4 +20,13 @@ export function mapToStudentDTO(student: Student): StudentDTO { firstName: student.firstName, lastName: student.lastName, }; -} \ No newline at end of file +} + +export function mapToStudent(studentData: StudentDTO): Student { + const student = new Student(); + student.username = studentData.username; + student.firstName = studentData.firstName; + student.lastName = studentData.lastName; + + return student; +} diff --git a/backend/src/interfaces/teacher-invitation.ts b/backend/src/interfaces/teacher-invitation.ts index c563968b..489e5565 100644 --- a/backend/src/interfaces/teacher-invitation.ts +++ b/backend/src/interfaces/teacher-invitation.ts @@ -1,6 +1,6 @@ -import { TeacherInvitation } from "../entities/classes/teacher-invitation.entity"; -import { ClassDTO, mapToClassDTO } from "./classes"; -import { mapToTeacherDTO, TeacherDTO } from "./teacher"; +import { TeacherInvitation } from "../entities/classes/teacher-invitation.entity.js"; +import { ClassDTO, mapToClassDTO } from "./classes.js"; +import { mapToTeacherDTO, TeacherDTO } from "./teacher.js"; export interface TeacherInvitationDTO { sender: string | TeacherDTO, @@ -22,4 +22,4 @@ export function mapToTeacherInvitationDTOIds(invitation: TeacherInvitation): Tea receiver: invitation.receiver.username, class: invitation.class.classId, }; -} \ No newline at end of file +} diff --git a/backend/src/interfaces/teacher.ts b/backend/src/interfaces/teacher.ts index 5aee089c..4f489c57 100644 --- a/backend/src/interfaces/teacher.ts +++ b/backend/src/interfaces/teacher.ts @@ -1,4 +1,4 @@ -import { Teacher } from "../entities/users/teacher.entity"; +import { Teacher } from "../entities/users/teacher.entity.js"; export interface TeacherDTO { id: string; @@ -20,4 +20,4 @@ export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { firstName: teacher.firstName, lastName: teacher.lastName, }; -} \ No newline at end of file +} diff --git a/backend/src/interfaces/user.ts b/backend/src/interfaces/user.ts new file mode 100644 index 00000000..02e27d83 --- /dev/null +++ b/backend/src/interfaces/user.ts @@ -0,0 +1,30 @@ +import { User } from "../entities/users/user.entity.js"; + +export interface UserDTO { + id?: string, + username: string; + firstName: string; + lastName: string; + endpoints?: { + self: string; + classes: string; + questions: string; + invitations: string; + }; +} + +export function mapToUserDTO(user: User): UserDTO { + return { + id: user.username, + username: user.username, + firstName: user.firstName, + lastName: user.lastName, + }; +} + +export function mapToUser(userData: UserDTO, userInstance: T): T { + userInstance.username = userData.username; + userInstance.firstName = userData.firstName; + userInstance.lastName = userData.lastName; + return userInstance; +} diff --git a/backend/src/routes/assignment.ts b/backend/src/routes/assignment.ts index d6965c49..9d83e755 100644 --- a/backend/src/routes/assignment.ts +++ b/backend/src/routes/assignment.ts @@ -1,5 +1,5 @@ import express from 'express' -import { getAllAssignmentsHandler, getAssignmentHandler } from '../controllers/assignments'; +import { getAllAssignmentsHandler, getAssignmentHandler } from '../controllers/assignments.js'; import groupRouter from './group.js'; const router = express.Router({ mergeParams: true }); @@ -28,4 +28,4 @@ router.get('/:id/questions', (req, res) => { router.use('/:assignmentid/groups', groupRouter); -export default router \ No newline at end of file +export default router diff --git a/backend/src/routes/class.ts b/backend/src/routes/class.ts index 369e6ff4..06154e60 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/class.ts @@ -1,5 +1,5 @@ import express from 'express' -import { getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../controllers/classes'; +import { getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../controllers/classes.js'; import assignmentRouter from './assignment.js'; const router = express.Router(); @@ -16,4 +16,4 @@ router.get('/:id/students', getClassStudentsHandler); router.use('/:classid/assignments', assignmentRouter); -export default router \ No newline at end of file +export default router diff --git a/backend/src/routes/group.ts b/backend/src/routes/group.ts index a8d4dbe5..76cdc61f 100644 --- a/backend/src/routes/group.ts +++ b/backend/src/routes/group.ts @@ -1,5 +1,5 @@ import express from 'express' -import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups'; +import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups.js'; const router = express.Router({ mergeParams: true }); // root endpoint used to search objects @@ -15,4 +15,4 @@ router.get('/:id/question', (req, res) => { }); }) -export default router \ No newline at end of file +export default router diff --git a/backend/src/routes/student.ts b/backend/src/routes/student.ts index bc806b4e..a5355c48 100644 --- a/backend/src/routes/student.ts +++ b/backend/src/routes/student.ts @@ -1,12 +1,24 @@ import express from 'express' -import { getAllStudentsHandler, getStudentAssignmentsHandler, getStudentClassesHandler, getStudentHandler } from '../controllers/students'; +import { + createStudentHandler, deleteStudentHandler, + getAllStudentsHandler, + getStudentAssignmentsHandler, + getStudentClassesHandler, + getStudentHandler +} from '../controllers/students.js'; const router = express.Router(); // root endpoint used to search objects router.get('/', getAllStudentsHandler); +router.post('/', createStudentHandler); + +router.delete('/:username', deleteStudentHandler); + // information about a student's profile -router.get('/:id', getStudentHandler); +router.get('/:username', getStudentHandler); + + // the list of classes a student is in router.get('/:id/classes', getStudentClassesHandler); @@ -18,10 +30,10 @@ router.get('/:id/submissions', (req, res) => { }); }) - + // the list of assignments a student has router.get('/:id/assignments', getStudentAssignmentsHandler); - + // the list of groups a student is in router.get('/:id/groups', (req, res) => { res.json({ @@ -36,4 +48,4 @@ router.get('/:id/questions', (req, res) => { }); }) -export default router \ No newline at end of file +export default router diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index e0804750..aaa51c10 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -1,5 +1,5 @@ -import { getAssignmentRepository, getClassRepository } from "../data/repositories"; -import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId } from "../interfaces/assignments"; +import { getAssignmentRepository, getClassRepository } from "../data/repositories.js"; +import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId } from "../interfaces/assignments.js"; export async function getAllAssignments(classid: string, full: boolean): Promise { const classRepository = getClassRepository(); @@ -8,7 +8,7 @@ export async function getAllAssignments(classid: string, full: boolean): Promise if (!cls) { return []; } - + const assignmentRepository = getAssignmentRepository(); const assignments = await assignmentRepository.findAllAssignmentsInClass(cls); @@ -26,7 +26,7 @@ export async function getAssignment(classid: string, id: number): Promise { const classRepository = getClassRepository(); @@ -11,7 +10,7 @@ export async function getAllClasses(full: boolean): Promise { @@ -64,4 +64,4 @@ export async function getAllGroups( } return groups.map(mapToGroupDTOId); -} \ No newline at end of file +} diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index a69cab85..24c9029b 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,26 +1,13 @@ -import { getClassRepository, getStudentRepository } from "../data/repositories"; -import { Class } from "../entities/classes/class.entity"; -import { Student } from "../entities/users/student.entity"; -import { ClassDTO, mapToClassDTO } from "../interfaces/classes"; -import { StudentDTO, mapToStudentDTO } from "../interfaces/students"; +import { getClassRepository, getStudentRepository } from "../data/repositories.js"; +import { Class } from "../entities/classes/class.entity.js"; +import { Student } from "../entities/users/student.entity.js"; +import { ClassDTO, mapToClassDTO } from "../interfaces/classes.js"; +import {UserService} from "./users.js"; - -export async function getAllStudents(): Promise { - const studentRepository = getStudentRepository(); - const students = await studentRepository.find({}); - - return students.map(mapToStudentDTO); -} - -export async function getStudent(username: string): Promise { - const studentRepository = getStudentRepository(); - const student = await studentRepository.findByUsername(username); - - if (!student) { - return null; +export class StudentService extends UserService { + constructor() { + super(getStudentRepository()); } - - return mapToStudentDTO(student); } async function fetchStudentClasses(username: string): Promise { diff --git a/backend/src/services/users.ts b/backend/src/services/users.ts new file mode 100644 index 00000000..bf88e916 --- /dev/null +++ b/backend/src/services/users.ts @@ -0,0 +1,39 @@ +import { UserRepository } from "../data/users/user-repository.js"; +import { UserDTO, mapToUser, mapToUserDTO } from "../interfaces/user.js"; +import {User} from "../entities/users/user.entity.js"; + +export class UserService { + protected repository: UserRepository; + + constructor(repository: UserRepository) { + this.repository = repository; + } + + async getAllUsers(): Promise { + const users = await this.repository.findAll(); + return users.map(mapToUserDTO); + } + + async getAllUserIds(): Promise { + const users = await this.getAllUsers(); + return users.map((user) => user.username); + } + + async getUserByUsername(username: string): Promise { + const user = await this.repository.findByUsername(username) + return user ? mapToUserDTO(user) : null; + } + + async createUser(userData: UserDTO, UserClass: new () => T): Promise { + const newUser = mapToUser(userData, new UserClass()); + await this.repository.save(newUser); + return newUser; + } + + async deleteUser(username: string): Promise { + const user = await this.getUserByUsername(username); + if (!user) return null; + await this.repository.deleteByUsername(username) + return mapToUserDTO(user); + } +} diff --git a/backend/src/util/translationHelper.ts b/backend/src/util/translationHelper.ts index f4443531..eb7141ee 100644 --- a/backend/src/util/translationHelper.ts +++ b/backend/src/util/translationHelper.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import yaml from 'js-yaml'; -import {FALLBACK_LANG} from "../../config"; +import {FALLBACK_LANG} from "../config.js"; export function loadTranslations(language: string): T { try { From 1b096b411b5c24230b4d64658832c4d283eeb553 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Sun, 9 Mar 2025 23:59:31 +0100 Subject: [PATCH 21/49] fix: integratie user + errors gefixt zodat het runt + format --- backend/src/app.ts | 2 +- backend/src/controllers/assignments.ts | 12 +- backend/src/controllers/classes.ts | 46 ++-- backend/src/controllers/groups.ts | 18 +- backend/src/controllers/learning-objects.ts | 2 +- backend/src/controllers/students.ts | 65 ++++-- backend/src/controllers/teachers.ts | 136 +++++------- backend/src/controllers/themes.ts | 3 +- backend/src/controllers/users.ts | 52 +++-- .../src/data/assignments/group-repository.ts | 21 +- backend/src/data/classes/class-repository.ts | 10 +- .../content/learning-object-repository.ts | 2 +- backend/src/data/dwengo-entity-repository.ts | 6 +- .../src/data/questions/answer-repository.ts | 2 +- .../src/data/questions/question-repository.ts | 16 +- backend/src/data/repositories.ts | 4 +- backend/src/data/users/student-repository.ts | 2 +- backend/src/data/users/teacher-repository.ts | 2 +- .../entities/assignments/assignment.entity.ts | 26 ++- .../src/entities/assignments/group.entity.ts | 19 +- .../entities/assignments/submission.entity.ts | 26 ++- .../classes/class-join-request.entity.ts | 24 +- backend/src/entities/classes/class.entity.ts | 14 +- .../classes/teacher-invitation.entity.ts | 27 ++- .../src/entities/content/attachment.entity.ts | 13 +- .../content/learning-object.entity.ts | 39 +++- .../entities/content/learning-path.entity.ts | 45 +++- .../src/entities/questions/answer.entity.ts | 20 +- .../src/entities/questions/question.entity.ts | 19 +- backend/src/entities/users/student.entity.ts | 14 +- backend/src/entities/users/teacher.entity.ts | 10 +- backend/src/interfaces/assignment.ts | 24 +- backend/src/interfaces/class.ts | 14 +- backend/src/interfaces/group.ts | 22 +- backend/src/interfaces/list.ts | 6 +- backend/src/interfaces/question.ts | 21 +- backend/src/interfaces/student.ts | 2 +- backend/src/interfaces/teacher-invitation.ts | 24 +- backend/src/interfaces/teacher.ts | 36 --- backend/src/interfaces/user.ts | 9 +- backend/src/mikro-orm.config.ts | 48 ++-- backend/src/routes/assignments.ts | 23 +- backend/src/routes/classes.ts | 17 +- backend/src/routes/groups.ts | 15 +- backend/src/routes/questions.ts | 28 +-- backend/src/routes/students.ts | 38 ++-- backend/src/routes/submissions.ts | 15 +- backend/src/routes/teachers.ts | 25 ++- backend/src/services/assignments.ts | 24 +- backend/src/services/class.ts | 73 ++++-- backend/src/services/groups.ts | 31 ++- backend/src/services/students.ts | 26 ++- backend/src/services/teachers.ts | 208 ++++++++---------- backend/src/services/users.ts | 18 +- backend/src/util/translation-helper.ts | 8 +- 55 files changed, 858 insertions(+), 594 deletions(-) delete mode 100644 backend/src/interfaces/teacher.ts diff --git a/backend/src/app.ts b/backend/src/app.ts index 37cfec67..20581e35 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -7,7 +7,7 @@ import learningPathRoutes from './routes/learning-paths.js'; import learningObjectRoutes from './routes/learning-objects.js'; import studentRoutes from './routes/students.js'; -import teacherRoutes from './routes/teachers.js' +import teacherRoutes from './routes/teachers.js'; import groupRoutes from './routes/groups.js'; import submissionRoutes from './routes/submissions.js'; import classRoutes from './routes/classes.js'; diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index ab0f951f..b1be1302 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,7 +1,7 @@ -import { Request, Response } from 'express' +import { Request, Response } from 'express'; import { getAllAssignments, getAssignment } from '../services/assignments.js'; -// typescript is annoy with with parameter forwarding from class.ts +// Typescript is annoy with with parameter forwarding from class.ts interface AssignmentParams { classid: string; id: string; @@ -9,7 +9,7 @@ interface AssignmentParams { export async function getAllAssignmentsHandler( req: Request, - res: Response, + res: Response ): Promise { const classid = req.params.classid; const full = req.query.full === 'true'; @@ -23,20 +23,20 @@ export async function getAllAssignmentsHandler( export async function getAssignmentHandler( req: Request, - res: Response, + res: Response ): Promise { const id = +req.params.id; const classid = req.params.classid; if (isNaN(id)) { - res.status(400).json({ error: "Assignment id must be a number" }); + res.status(400).json({ error: 'Assignment id must be a number' }); return; } const assignment = await getAssignment(classid, id); if (!assignment) { - res.status(404).json({ error: "Assignment not found" }); + res.status(404).json({ error: 'Assignment not found' }); return; } diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index 6fb9d7f4..b8061b5a 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,40 +1,44 @@ import { Request, Response } from 'express'; -import { getAllClasses, getClass, getClassStudents, getClassStudentsIds, getClassTeacherInvitations } from '../services/class.js'; -import { ClassDTO } from '../interfaces/classes.js'; +import { + getAllClasses, + getClass, + getClassStudents, + getClassStudentsIds, + getClassTeacherInvitations, +} from '../services/class.js'; export async function getAllClassesHandler( req: Request, - res: Response, + res: Response ): Promise { - const full = req.query.full === "true"; + const full = req.query.full === 'true'; const classes = await getAllClasses(full); res.json({ - classes: classes + classes: classes, }); } export async function getClassHandler( req: Request, - res: Response, + res: Response ): Promise { try { const classId = req.params.id; const cls = await getClass(classId); if (!cls) { - res.status(404).json({ error: "Student not found" }); + res.status(404).json({ error: 'Student not found' }); return; - } else { - cls.endpoints = { - self: `${req.baseUrl}/${req.params.id}`, - invitations: `${req.baseUrl}/${req.params.id}/invitations`, - assignments: `${req.baseUrl}/${req.params.id}/assignments`, - students: `${req.baseUrl}/${req.params.id}/students`, - } - - res.json(cls); } + cls.endpoints = { + self: `${req.baseUrl}/${req.params.id}`, + invitations: `${req.baseUrl}/${req.params.id}/invitations`, + assignments: `${req.baseUrl}/${req.params.id}/assignments`, + students: `${req.baseUrl}/${req.params.id}/students`, + }; + + res.json(cls); } catch (error) { console.error('Error fetching learning objects:', error); res.status(500).json({ error: 'Internal server error' }); @@ -43,12 +47,12 @@ export async function getClassHandler( export async function getClassStudentsHandler( req: Request, - res: Response, + res: Response ): Promise { const classId = req.params.id; - const full = req.query.full === "true"; + const full = req.query.full === 'true'; - let students = full + const students = full ? await getClassStudents(classId) : await getClassStudentsIds(classId); @@ -59,10 +63,10 @@ export async function getClassStudentsHandler( export async function getTeacherInvitationsHandler( req: Request, - res: Response, + res: Response ): Promise { const classId = req.params.id; - const full = req.query.full === "true"; // TODO: not implemented yet + const full = req.query.full === 'true'; // TODO: not implemented yet const invitations = await getClassTeacherInvitations(classId, full); diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index d301c98d..e484c409 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -1,7 +1,7 @@ import { Request, Response } from 'express'; import { getAllGroups, getGroup } from '../services/groups.js'; -// typescript is annoywith with parameter forwarding from class.ts +// Typescript is annoywith with parameter forwarding from class.ts interface GroupParams { classid: string; assignmentid: string; @@ -10,21 +10,21 @@ interface GroupParams { export async function getGroupHandler( req: Request, - res: Response, + res: Response ): Promise { const classId = req.params.classid; - const full = req.query.full === "true"; + const full = req.query.full === 'true'; const assignmentId = +req.params.assignmentid; if (isNaN(assignmentId)) { - res.status(400).json({ error: "Assignment id must be a number" }); + res.status(400).json({ error: 'Assignment id must be a number' }); return; } - const groupId = +req.params.groupid!; // can't be undefined + const groupId = +req.params.groupid!; // Can't be undefined if (isNaN(groupId)) { - res.status(400).json({ error: "Group id must be a number" }); + res.status(400).json({ error: 'Group id must be a number' }); return; } @@ -35,15 +35,15 @@ export async function getGroupHandler( export async function getAllGroupsHandler( req: Request, - res: Response, + res: Response ): Promise { const classId = req.params.classid; - const full = req.query.full === "true"; + const full = req.query.full === 'true'; const assignmentId = +req.params.assignmentid; if (isNaN(assignmentId)) { - res.status(400).json({ error: "Assignment id must be a number" }); + res.status(400).json({ error: 'Assignment id must be a number' }); return; } diff --git a/backend/src/controllers/learning-objects.ts b/backend/src/controllers/learning-objects.ts index c8a51734..12c0201f 100644 --- a/backend/src/controllers/learning-objects.ts +++ b/backend/src/controllers/learning-objects.ts @@ -5,7 +5,7 @@ import { getLearningObjectsFromPath, } from '../services/learning-objects.js'; import { FALLBACK_LANG } from '../config.js'; -import { FilteredLearningObject } from '../interfaces/learning-path'; +import { FilteredLearningObject } from '../interfaces/learning-path.js'; export async function getAllLearningObjects( req: Request, diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index b4fe7b47..2134a9f2 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -2,43 +2,62 @@ import { Request, Response } from 'express'; import { getStudentClasses, getStudentClassIds, - StudentService + StudentService, } from '../services/students.js'; -import { ClassDTO } from '../interfaces/classes.js'; +import { ClassDTO } from '../interfaces/class.js'; import { getAllAssignments } from '../services/assignments.js'; -import {createUserHandler, deleteUserHandler, getAllUsersHandler, getUserHandler} from "./users.js"; -import { Student } from "../entities/users/student.entity.js"; +import { + createUserHandler, + deleteUserHandler, + getAllUsersHandler, + getUserHandler, +} from './users.js'; +import { Student } from '../entities/users/student.entity.js'; // TODO: accept arguments (full, ...) // TODO: endpoints -export async function getAllStudentsHandler (req: Request, res: Response): Promise { +export async function getAllStudentsHandler( + req: Request, + res: Response +): Promise { await getAllUsersHandler(req, res, new StudentService()); } -export async function getStudentHandler(req: Request, res: Response): Promise { +export async function getStudentHandler( + req: Request, + res: Response +): Promise { await getUserHandler(req, res, new StudentService()); } -export async function createStudentHandler(req: Request, res: Response): Promise { +export async function createStudentHandler( + req: Request, + res: Response +): Promise { await createUserHandler(req, res, new StudentService(), Student); } -export async function deleteStudentHandler(req: Request, res: Response): Promise { +export async function deleteStudentHandler( + req: Request, + res: Response +): Promise { await deleteUserHandler(req, res, new StudentService()); } - -export async function getStudentClassesHandler ( +export async function getStudentClassesHandler( req: Request, - res: Response, + res: Response ): Promise { try { const full = req.query.full === 'true'; const username = req.params.id; let classes: ClassDTO[] | string[]; - if (full) classes = await getStudentClasses(username); - else classes = await getStudentClassIds(username); + if (full) { + classes = await getStudentClasses(username); + } else { + classes = await getStudentClassIds(username); + } res.json({ classes: classes, @@ -47,7 +66,7 @@ export async function getStudentClassesHandler ( classes: `${req.baseUrl}/${req.params.id}/invitations`, questions: `${req.baseUrl}/${req.params.id}/assignments`, students: `${req.baseUrl}/${req.params.id}/students`, - } + }, }); } catch (error) { console.error('Error fetching learning objects:', error); @@ -57,22 +76,26 @@ export async function getStudentClassesHandler ( // TODO // Might not be fully correct depending on if -// a class has an assignment, that all students -// have this assignment. +// A class has an assignment, that all students +// Have this assignment. export async function getStudentAssignmentsHandler( req: Request, - res: Response, + res: Response ): Promise { const full = req.query.full === 'true'; const username = req.params.id; const classes = await getStudentClasses(username); - const assignments = (await Promise.all(classes.map(async cls => await getAllAssignments(cls.id, full)))).flat(); + const assignments = ( + await Promise.all( + classes.map(async (cls) => { + return await getAllAssignments(cls.id, full); + }) + ) + ).flat(); res.json({ - assignments: assignments + assignments: assignments, }); } - - diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index d3b6a4db..c083710d 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -1,92 +1,53 @@ import { Request, Response } from 'express'; +import { TeacherUserService, TeacherService } from '../services/teachers.js'; +import { ClassDTO } from '../interfaces/class.js'; +import { StudentDTO } from '../interfaces/student.js'; +import { QuestionDTO, QuestionId } from '../interfaces/question.js'; import { - createTeacher, - deleteTeacher, - getTeacherByUsername, - getClassesByTeacher, - getClassIdsByTeacher, - getAllTeachers, - getAllTeachersIds, getStudentsByTeacher, getStudentIdsByTeacher, getQuestionsByTeacher, getQuestionIdsByTeacher -} from '../services/teachers.js'; -import {TeacherDTO} from "../interfaces/teacher"; -import {ClassDTO} from "../interfaces/class"; -import {StudentDTO} from "../interfaces/student"; -import {QuestionDTO, QuestionId} from "../interfaces/question"; + createUserHandler, + deleteUserHandler, + getAllUsersHandler, + getUserHandler, +} from './users.js'; +import { Teacher } from '../entities/users/teacher.entity.js'; -export async function getTeacherHandler(req: Request, res: Response): Promise { - try { - const full = req.query.full === 'true'; - const username = req.query.username as string; +export async function getAllTeachersHandler( + req: Request, + res: Response +): Promise { + await getAllUsersHandler(req, res, new TeacherUserService()); +} - if (username){ - const teacher = await getTeacherByUsername(username); - if (!teacher){ - res.status(404).json({ error: `Teacher with username '${username}' not found.` }); - return; - } - res.json(teacher); - return; - } - - let teachers: TeacherDTO[] | string[]; - - if (full) teachers = await getAllTeachers(); - else teachers = await getAllTeachersIds(); - - res.json(teachers); - } catch (error) { - console.error("❌ Error fetching teachers:", error); - res.status(500).json({ error: "Internal server error" }); - } +export async function getTeacherHandler( + req: Request, + res: Response +): Promise { + await getUserHandler(req, res, new TeacherUserService()); } export async function createTeacherHandler( req: Request, res: Response ): Promise { - try { - const teacherData = req.body as TeacherDTO; - - if (!teacherData.username || !teacherData.firstName || !teacherData.lastName) { - res.status(400).json({ error: 'Missing required fields: username, firstName, lastName' }); - return; - } - - const newTeacher = await createTeacher(teacherData); - res.status(201).json(newTeacher); - } catch (error) { - console.error('Error creating teacher:', error); - res.status(500).json({ error: 'Internal server error' }); - } + await createUserHandler( + req, + res, + new TeacherUserService(), + Teacher + ); } export async function deleteTeacherHandler( req: Request, res: Response ): Promise { - try { - const username = req.params.username as string; - - if (!username) { - res.status(400).json({ error: 'Missing required field: username' }); - return; - } - - const deletedTeacher = await deleteTeacher(username); - - if (!deletedTeacher) { - res.status(400).json({ error: `Did not find teacher with username ${username}` }); - return; - } - - res.status(201).json(deletedTeacher); - } catch (error) { - console.error('Error deleting teacher:', error); - res.status(500).json({ error: 'Internal server error' }); - } + await deleteUserHandler(req, res, new TeacherUserService()); } -export async function getTeacherClassHandler(req: Request, res: Response): Promise { +export async function getTeacherClassHandler( + req: Request, + res: Response +): Promise { try { const username = req.params.username as string; const full = req.query.full === 'true'; @@ -96,10 +57,11 @@ export async function getTeacherClassHandler(req: Request, res: Response): Promi return; } - let classes: ClassDTO[] | string[]; + const teacherService = new TeacherService(); - if (full) classes = await getClassesByTeacher(username); - else classes = await getClassIdsByTeacher(username); + const classes: ClassDTO[] | string[] = full + ? await teacherService.getClassesByTeacher(username) + : await teacherService.getClassIdsByTeacher(username); res.status(201).json(classes); } catch (error) { @@ -108,7 +70,10 @@ export async function getTeacherClassHandler(req: Request, res: Response): Promi } } -export async function getTeacherStudentHandler(req: Request, res: Response): Promise { +export async function getTeacherStudentHandler( + req: Request, + res: Response +): Promise { try { const username = req.params.username as string; const full = req.query.full === 'true'; @@ -118,10 +83,11 @@ export async function getTeacherStudentHandler(req: Request, res: Response): Pro return; } - let students: StudentDTO[] | string[]; + const teacherService = new TeacherService(); - if (full) students = await getStudentsByTeacher(username); - else students = await getStudentIdsByTeacher(username); + const students: StudentDTO[] | string[] = full + ? await teacherService.getStudentsByTeacher(username) + : await teacherService.getStudentIdsByTeacher(username); res.status(201).json(students); } catch (error) { @@ -130,7 +96,10 @@ export async function getTeacherStudentHandler(req: Request, res: Response): Pro } } -export async function getTeacherQuestionHandler(req: Request, res: Response): Promise { +export async function getTeacherQuestionHandler( + req: Request, + res: Response +): Promise { try { const username = req.params.username as string; const full = req.query.full === 'true'; @@ -140,10 +109,11 @@ export async function getTeacherQuestionHandler(req: Request, res: Response): Pr return; } - let questions: QuestionDTO[] | QuestionId[]; + const teacherService = new TeacherService(); - if (full) questions = await getQuestionsByTeacher(username); - else questions = await getQuestionIdsByTeacher(username); + const questions: QuestionDTO[] | QuestionId[] = full + ? await teacherService.getQuestionsByTeacher(username) + : await teacherService.getQuestionIdsByTeacher(username); res.status(201).json(questions); } catch (error) { @@ -151,5 +121,3 @@ export async function getTeacherQuestionHandler(req: Request, res: Response): Pr res.status(500).json({ error: 'Internal server error' }); } } - - diff --git a/backend/src/controllers/themes.ts b/backend/src/controllers/themes.ts index 208b27d1..30cb2b13 100644 --- a/backend/src/controllers/themes.ts +++ b/backend/src/controllers/themes.ts @@ -1,7 +1,6 @@ import { Request, Response } from 'express'; import { themes } from '../data/themes.js'; -import { loadTranslations } from "../util/translation-helper.js"; -import { FALLBACK_LANG } from '../config.js'; +import { loadTranslations } from '../util/translation-helper.js'; interface Translations { curricula_page: { diff --git a/backend/src/controllers/users.ts b/backend/src/controllers/users.ts index 4b29617e..8b256a0e 100644 --- a/backend/src/controllers/users.ts +++ b/backend/src/controllers/users.ts @@ -1,30 +1,29 @@ import { Request, Response } from 'express'; -import { UserService } from "../services/users.js"; -import {UserDTO} from "../interfaces/user.js"; -import {User} from "../entities/users/user.entity.js"; +import { UserService } from '../services/users.js'; +import { UserDTO } from '../interfaces/user.js'; +import { User } from '../entities/users/user.entity.js'; export async function getAllUsersHandler( req: Request, res: Response, service: UserService -): Promise { +): Promise { try { const full = req.query.full === 'true'; - let users: UserDTO[] | string[] = full + const users: UserDTO[] | string[] = full ? await service.getAllUsers() : await service.getAllUserIds(); - if (!users){ + if (!users) { res.status(404).json({ error: `Users not found.` }); return; } res.status(201).json(users); - } catch (error) { - console.error("❌ Error fetching users:", error); - res.status(500).json({ error: "Internal server error" }); + console.error('❌ Error fetching users:', error); + res.status(500).json({ error: 'Internal server error' }); } } @@ -32,7 +31,7 @@ export async function getUserHandler( req: Request, res: Response, service: UserService -): Promise { +): Promise { try { const username = req.params.username as string; @@ -43,16 +42,17 @@ export async function getUserHandler( const user = await service.getUserByUsername(username); - if (!user){ - res.status(404).json({ error: `User with username '${username}' not found.` }); + if (!user) { + res.status(404).json({ + error: `User with username '${username}' not found.`, + }); return; } res.status(201).json(user); - } catch (error) { - console.error("❌ Error fetching users:", error); - res.status(500).json({ error: "Internal server error" }); + console.error('❌ Error fetching users:', error); + res.status(500).json({ error: 'Internal server error' }); } } @@ -63,23 +63,25 @@ export async function createUserHandler( UserClass: new () => T ) { try { - console.log("req", req) + console.log('req', req); const userData = req.body as UserDTO; if (!userData.username || !userData.firstName || !userData.lastName) { - res.status(400).json({ error: "Missing required fields: username, firstName, lastName" }); + res.status(400).json({ + error: 'Missing required fields: username, firstName, lastName', + }); return; } const newUser = await service.createUser(userData, UserClass); res.status(201).json(newUser); } catch (error) { - console.error("❌ Error creating user:", error); - res.status(500).json({ error: "Internal server error" }); + console.error('❌ Error creating user:', error); + res.status(500).json({ error: 'Internal server error' }); } } -export async function deleteUserHandler ( +export async function deleteUserHandler( req: Request, res: Response, service: UserService @@ -88,19 +90,21 @@ export async function deleteUserHandler ( const username = req.params.username; if (!username) { - res.status(400).json({ error: "Missing required field: username" }); + res.status(400).json({ error: 'Missing required field: username' }); return; } const deletedUser = await service.deleteUser(username); if (!deletedUser) { - res.status(404).json({ error: `User with username '${username}' not found.` }); + res.status(404).json({ + error: `User with username '${username}' not found.`, + }); return; } res.status(200).json(deletedUser); } catch (error) { - console.error("❌ Error deleting user:", error); - res.status(500).json({ error: "Internal server error" }); + console.error('❌ Error deleting user:', error); + res.status(500).json({ error: 'Internal server error' }); } } diff --git a/backend/src/data/assignments/group-repository.ts b/backend/src/data/assignments/group-repository.ts index c8770eb5..e9b668b9 100644 --- a/backend/src/data/assignments/group-repository.ts +++ b/backend/src/data/assignments/group-repository.ts @@ -8,21 +8,20 @@ export class GroupRepository extends DwengoEntityRepository { groupNumber: number ): Promise { return this.findOne( - { - assignment: assignment, - groupNumber: groupNumber, - }, - { populate: ["members"] }, - ); + { + assignment: assignment, + groupNumber: groupNumber, + }, + { populate: ['members'] } + ); } public findAllGroupsForAssignment( assignment: Assignment ): Promise { - return this.findAll({ - where: { assignment: assignment }, - populate: ["members"] - }, - ); + return this.findAll({ + where: { assignment: assignment }, + populate: ['members'], + }); } public deleteByAssignmentAndGroupNumber( assignment: Assignment, diff --git a/backend/src/data/classes/class-repository.ts b/backend/src/data/classes/class-repository.ts index 9fd50d75..4f2f5b0e 100644 --- a/backend/src/data/classes/class-repository.ts +++ b/backend/src/data/classes/class-repository.ts @@ -1,13 +1,13 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Class } from '../../entities/classes/class.entity.js'; import { Student } from '../../entities/users/student.entity.js'; -import {Teacher} from "../../entities/users/teacher.entity"; +import { Teacher } from '../../entities/users/teacher.entity'; export class ClassRepository extends DwengoEntityRepository { public findById(id: string): Promise { return this.findOne( { classId: id }, - { populate: ["students", "teachers"] }, + { populate: ['students', 'teachers'] } ); } public deleteById(id: string): Promise { @@ -16,14 +16,14 @@ export class ClassRepository extends DwengoEntityRepository { public findByStudent(student: Student): Promise { return this.find( { students: student }, - { populate: ["students", "teachers"] } // voegt student en teacher objecten toe - ) + { populate: ['students', 'teachers'] } // Voegt student en teacher objecten toe + ); } public findByTeacher(teacher: Teacher): Promise { return this.find( { teachers: teacher }, - { populate: ["students", "teachers"] } + { populate: ['students', 'teachers'] } ); } } diff --git a/backend/src/data/content/learning-object-repository.ts b/backend/src/data/content/learning-object-repository.ts index d8b07943..4de31076 100644 --- a/backend/src/data/content/learning-object-repository.ts +++ b/backend/src/data/content/learning-object-repository.ts @@ -1,7 +1,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { LearningObject } from '../../entities/content/learning-object.entity.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; -import {Teacher} from "../../entities/users/teacher.entity"; +import { Teacher } from '../../entities/users/teacher.entity'; export class LearningObjectRepository extends DwengoEntityRepository { public findByIdentifier( diff --git a/backend/src/data/dwengo-entity-repository.ts b/backend/src/data/dwengo-entity-repository.ts index 368f3a2c..e29d9ede 100644 --- a/backend/src/data/dwengo-entity-repository.ts +++ b/backend/src/data/dwengo-entity-repository.ts @@ -4,13 +4,13 @@ export abstract class DwengoEntityRepository< T extends object, > extends EntityRepository { public async save(entity: T) { - let em = this.getEntityManager(); + const em = this.getEntityManager(); em.persist(entity); await em.flush(); } public async deleteWhere(query: FilterQuery) { - let toDelete = await this.findOne(query); - let em = this.getEntityManager(); + const toDelete = await this.findOne(query); + const em = this.getEntityManager(); if (toDelete) { em.remove(toDelete); await em.flush(); diff --git a/backend/src/data/questions/answer-repository.ts b/backend/src/data/questions/answer-repository.ts index 6a2629f4..6c45211c 100644 --- a/backend/src/data/questions/answer-repository.ts +++ b/backend/src/data/questions/answer-repository.ts @@ -9,7 +9,7 @@ export class AnswerRepository extends DwengoEntityRepository { author: Teacher; content: string; }): Promise { - let answerEntity = new Answer(); + const answerEntity = new Answer(); answerEntity.toQuestion = answer.toQuestion; answerEntity.author = answer.author; answerEntity.content = answer.content; diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index 05430ddd..7dee3b96 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -2,7 +2,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Question } from '../../entities/questions/question.entity.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; import { Student } from '../../entities/users/student.entity.js'; -import {LearningObject} from "../../entities/content/learning-object.entity"; +import { LearningObject } from '../../entities/content/learning-object.entity'; export class QuestionRepository extends DwengoEntityRepository { public createQuestion(question: { @@ -10,7 +10,7 @@ export class QuestionRepository extends DwengoEntityRepository { author: Student; content: string; }): Promise { - let questionEntity = new Question(); + const questionEntity = new Question(); questionEntity.learningObjectHruid = question.loId.hruid; questionEntity.learningObjectLanguage = question.loId.language; questionEntity.learningObjectVersion = question.loId.version; @@ -44,12 +44,16 @@ export class QuestionRepository extends DwengoEntityRepository { }); } - public async findAllByLearningObjects(learningObjects: LearningObject[]): Promise { - const objectIdentifiers = learningObjects.map(lo => ({ + public async findAllByLearningObjects( + learningObjects: LearningObject[] + ): Promise { + const objectIdentifiers = learningObjects.map((lo) => { + return { learningObjectHruid: lo.hruid, learningObjectLanguage: lo.language, - learningObjectVersion: lo.version - })); + learningObjectVersion: lo.version, + }; + }); return this.findAll({ where: { $or: objectIdentifiers }, diff --git a/backend/src/data/repositories.ts b/backend/src/data/repositories.ts index e65bb882..74e9a07e 100644 --- a/backend/src/data/repositories.ts +++ b/backend/src/data/repositories.ts @@ -59,7 +59,9 @@ function repositoryGetter>( } /* Users */ -export const getUserRepository = repositoryGetter>(User); +export const getUserRepository = repositoryGetter>( + User +); export const getStudentRepository = repositoryGetter< Student, StudentRepository diff --git a/backend/src/data/users/student-repository.ts b/backend/src/data/users/student-repository.ts index c553aab8..6835e430 100644 --- a/backend/src/data/users/student-repository.ts +++ b/backend/src/data/users/student-repository.ts @@ -1,4 +1,4 @@ import { Student } from '../../entities/users/student.entity.js'; -import {UserRepository} from "./user-repository.js"; +import { UserRepository } from './user-repository.js'; export class StudentRepository extends UserRepository {} diff --git a/backend/src/data/users/teacher-repository.ts b/backend/src/data/users/teacher-repository.ts index 9940b4bd..4c4f7687 100644 --- a/backend/src/data/users/teacher-repository.ts +++ b/backend/src/data/users/teacher-repository.ts @@ -1,4 +1,4 @@ import { Teacher } from '../../entities/users/teacher.entity.js'; -import {UserRepository} from "./user-repository.js"; +import { UserRepository } from './user-repository.js'; export class TeacherRepository extends UserRepository {} diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index 785a8b9c..f6e3c3eb 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -11,9 +11,18 @@ import { Group } from './group.entity.js'; import { Language } from '../content/language.js'; import { AssignmentRepository } from '../../data/assignments/assignment-repository.js'; -@Entity({ repository: () => AssignmentRepository }) +@Entity({ + repository: () => { + return AssignmentRepository; + }, +}) export class Assignment { - @ManyToOne({ entity: () => Class, primary: true }) + @ManyToOne({ + entity: () => { + return Class; + }, + primary: true, + }) within!: Class; @PrimaryKey({ type: 'number' }) @@ -28,9 +37,18 @@ export class Assignment { @Property({ type: 'string' }) learningPathHruid!: string; - @Enum({ items: () => Language }) + @Enum({ + items: () => { + return Language; + }, + }) learningPathLanguage!: Language; - @OneToMany({ entity: () => Group, mappedBy: 'assignment' }) + @OneToMany({ + entity: () => { + return Group; + }, + mappedBy: 'assignment', + }) groups!: Group[]; } diff --git a/backend/src/entities/assignments/group.entity.ts b/backend/src/entities/assignments/group.entity.ts index cb4cd6e6..9c2ed2cf 100644 --- a/backend/src/entities/assignments/group.entity.ts +++ b/backend/src/entities/assignments/group.entity.ts @@ -3,14 +3,27 @@ import { Assignment } from './assignment.entity.js'; import { Student } from '../users/student.entity.js'; import { GroupRepository } from '../../data/assignments/group-repository.js'; -@Entity({ repository: () => GroupRepository }) +@Entity({ + repository: () => { + return GroupRepository; + }, +}) export class Group { - @ManyToOne({ entity: () => Assignment, primary: true }) + @ManyToOne({ + entity: () => { + return Assignment; + }, + primary: true, + }) assignment!: Assignment; @PrimaryKey({ type: 'integer' }) groupNumber!: number; - @ManyToMany({ entity: () => Student }) + @ManyToMany({ + entity: () => { + return Student; + }, + }) members!: Student[]; } diff --git a/backend/src/entities/assignments/submission.entity.ts b/backend/src/entities/assignments/submission.entity.ts index 26269020..2836c8dc 100644 --- a/backend/src/entities/assignments/submission.entity.ts +++ b/backend/src/entities/assignments/submission.entity.ts @@ -4,12 +4,21 @@ import { Entity, Enum, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { Language } from '../content/language.js'; import { SubmissionRepository } from '../../data/assignments/submission-repository.js'; -@Entity({ repository: () => SubmissionRepository }) +@Entity({ + repository: () => { + return SubmissionRepository; + }, +}) export class Submission { @PrimaryKey({ type: 'string' }) learningObjectHruid!: string; - @Enum({ items: () => Language, primary: true }) + @Enum({ + items: () => { + return Language; + }, + primary: true, + }) learningObjectLanguage!: Language; @PrimaryKey({ type: 'string' }) @@ -18,13 +27,22 @@ export class Submission { @PrimaryKey({ type: 'integer' }) submissionNumber!: number; - @ManyToOne({ entity: () => Student }) + @ManyToOne({ + entity: () => { + return Student; + }, + }) submitter!: Student; @Property({ type: 'datetime' }) submissionTime!: Date; - @ManyToOne({ entity: () => Group, nullable: true }) + @ManyToOne({ + entity: () => { + return Group; + }, + nullable: true, + }) onBehalfOf?: Group; @Property({ type: 'json' }) diff --git a/backend/src/entities/classes/class-join-request.entity.ts b/backend/src/entities/classes/class-join-request.entity.ts index 0636e044..6055454b 100644 --- a/backend/src/entities/classes/class-join-request.entity.ts +++ b/backend/src/entities/classes/class-join-request.entity.ts @@ -3,15 +3,31 @@ import { Student } from '../users/student.entity.js'; import { Class } from './class.entity.js'; import { ClassJoinRequestRepository } from '../../data/classes/class-join-request-repository.js'; -@Entity({ repository: () => ClassJoinRequestRepository }) +@Entity({ + repository: () => { + return ClassJoinRequestRepository; + }, +}) export class ClassJoinRequest { - @ManyToOne({ entity: () => Student, primary: true }) + @ManyToOne({ + entity: () => { + return Student; + }, + primary: true, + }) requester!: Student; - @ManyToOne({ entity: () => Class, primary: true }) + @ManyToOne({ + entity: () => { + return Class; + }, + primary: true, + }) class!: Class; - @Enum(() => ClassJoinRequestStatus) + @Enum(() => { + return ClassJoinRequestStatus; + }) status!: ClassJoinRequestStatus; } diff --git a/backend/src/entities/classes/class.entity.ts b/backend/src/entities/classes/class.entity.ts index 06d31479..b40b5baf 100644 --- a/backend/src/entities/classes/class.entity.ts +++ b/backend/src/entities/classes/class.entity.ts @@ -10,7 +10,11 @@ import { Teacher } from '../users/teacher.entity.js'; import { Student } from '../users/student.entity.js'; import { ClassRepository } from '../../data/classes/class-repository.js'; -@Entity({ repository: () => ClassRepository }) +@Entity({ + repository: () => { + return ClassRepository; + }, +}) export class Class { @PrimaryKey() classId = v4(); @@ -18,9 +22,13 @@ export class Class { @Property({ type: 'string' }) displayName!: string; - @ManyToMany(() => Teacher) + @ManyToMany(() => { + return Teacher; + }) teachers!: Collection; - @ManyToMany(() => Student) + @ManyToMany(() => { + return Student; + }) students!: Collection; } diff --git a/backend/src/entities/classes/teacher-invitation.entity.ts b/backend/src/entities/classes/teacher-invitation.entity.ts index 42700d3a..877a183b 100644 --- a/backend/src/entities/classes/teacher-invitation.entity.ts +++ b/backend/src/entities/classes/teacher-invitation.entity.ts @@ -6,14 +6,33 @@ import { TeacherInvitationRepository } from '../../data/classes/teacher-invitati /** * Invitation of a teacher into a class (in order to teach it). */ -@Entity({ repository: () => TeacherInvitationRepository }) +@Entity({ + repository: () => { + return TeacherInvitationRepository; + }, +}) export class TeacherInvitation { - @ManyToOne({ entity: () => Teacher, primary: true }) + @ManyToOne({ + entity: () => { + return Teacher; + }, + primary: true, + }) sender!: Teacher; - @ManyToOne({ entity: () => Teacher, primary: true }) + @ManyToOne({ + entity: () => { + return Teacher; + }, + primary: true, + }) receiver!: Teacher; - @ManyToOne({ entity: () => Class, primary: true }) + @ManyToOne({ + entity: () => { + return Class; + }, + primary: true, + }) class!: Class; } diff --git a/backend/src/entities/content/attachment.entity.ts b/backend/src/entities/content/attachment.entity.ts index 7f14d178..8225ebf2 100644 --- a/backend/src/entities/content/attachment.entity.ts +++ b/backend/src/entities/content/attachment.entity.ts @@ -2,9 +2,18 @@ import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { LearningObject } from './learning-object.entity.js'; import { AttachmentRepository } from '../../data/content/attachment-repository.js'; -@Entity({ repository: () => AttachmentRepository }) +@Entity({ + repository: () => { + return AttachmentRepository; + }, +}) export class Attachment { - @ManyToOne({ entity: () => LearningObject, primary: true }) + @ManyToOne({ + entity: () => { + return LearningObject; + }, + primary: true, + }) learningObject!: LearningObject; @PrimaryKey({ type: 'integer' }) diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index 78d4aa00..888de5e3 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -22,18 +22,31 @@ export class ReturnValue { callbackSchema!: string; } -@Entity({ repository: () => LearningObjectRepository }) +@Entity({ + repository: () => { + return LearningObjectRepository; + }, +}) export class LearningObject { @PrimaryKey({ type: 'string' }) hruid!: string; - @Enum({ items: () => Language, primary: true }) + @Enum({ + items: () => { + return Language; + }, + primary: true, + }) language!: Language; @PrimaryKey({ type: 'string' }) version: string = '1'; - @ManyToMany({ entity: () => Teacher }) + @ManyToMany({ + entity: () => { + return Teacher; + }, + }) admins!: Teacher[]; @Property({ type: 'string' }) @@ -57,7 +70,12 @@ export class LearningObject { @Property({ type: 'array' }) skosConcepts!: string[]; - @Embedded({ entity: () => EducationalGoal, array: true }) + @Embedded({ + entity: () => { + return EducationalGoal; + }, + array: true, + }) educationalGoals: EducationalGoal[] = []; @Property({ type: 'string' }) @@ -72,7 +90,11 @@ export class LearningObject { @Property({ type: 'integer' }) estimatedTime!: number; - @Embedded({ entity: () => ReturnValue }) + @Embedded({ + entity: () => { + return ReturnValue; + }, + }) returnValue!: ReturnValue; @Property({ type: 'bool' }) @@ -81,7 +103,12 @@ export class LearningObject { @Property({ type: 'string', nullable: true }) contentLocation?: string; - @OneToMany({ entity: () => Attachment, mappedBy: 'learningObject' }) + @OneToMany({ + entity: () => { + return Attachment; + }, + mappedBy: 'learningObject', + }) attachments: Attachment[] = []; @Property({ type: 'blob' }) diff --git a/backend/src/entities/content/learning-path.entity.ts b/backend/src/entities/content/learning-path.entity.ts index de62aa15..34026461 100644 --- a/backend/src/entities/content/learning-path.entity.ts +++ b/backend/src/entities/content/learning-path.entity.ts @@ -12,15 +12,28 @@ import { Language } from './language.js'; import { Teacher } from '../users/teacher.entity.js'; import { LearningPathRepository } from '../../data/content/learning-path-repository.js'; -@Entity({ repository: () => LearningPathRepository }) +@Entity({ + repository: () => { + return LearningPathRepository; + }, +}) export class LearningPath { @PrimaryKey({ type: 'string' }) hruid!: string; - @Enum({ items: () => Language, primary: true }) + @Enum({ + items: () => { + return Language; + }, + primary: true, + }) language!: Language; - @ManyToMany({ entity: () => Teacher }) + @ManyToMany({ + entity: () => { + return Teacher; + }, + }) admins!: Teacher[]; @Property({ type: 'string' }) @@ -32,7 +45,12 @@ export class LearningPath { @Property({ type: 'blob' }) image!: string; - @Embedded({ entity: () => LearningPathNode, array: true }) + @Embedded({ + entity: () => { + return LearningPathNode; + }, + array: true, + }) nodes: LearningPathNode[] = []; } @@ -41,7 +59,11 @@ export class LearningPathNode { @Property({ type: 'string' }) learningObjectHruid!: string; - @Enum({ items: () => Language }) + @Enum({ + items: () => { + return Language; + }, + }) language!: Language; @Property({ type: 'string' }) @@ -53,7 +75,12 @@ export class LearningPathNode { @Property({ type: 'bool' }) startNode!: boolean; - @Embedded({ entity: () => LearningPathTransition, array: true }) + @Embedded({ + entity: () => { + return LearningPathTransition; + }, + array: true, + }) transitions!: LearningPathTransition[]; } @@ -62,6 +89,10 @@ export class LearningPathTransition { @Property({ type: 'string' }) condition!: string; - @OneToOne({ entity: () => LearningPathNode }) + @OneToOne({ + entity: () => { + return LearningPathNode; + }, + }) next!: LearningPathNode; } diff --git a/backend/src/entities/questions/answer.entity.ts b/backend/src/entities/questions/answer.entity.ts index 7fb64575..b73c7014 100644 --- a/backend/src/entities/questions/answer.entity.ts +++ b/backend/src/entities/questions/answer.entity.ts @@ -3,12 +3,26 @@ import { Question } from './question.entity.js'; import { Teacher } from '../users/teacher.entity.js'; import { AnswerRepository } from '../../data/questions/answer-repository.js'; -@Entity({ repository: () => AnswerRepository }) +@Entity({ + repository: () => { + return AnswerRepository; + }, +}) export class Answer { - @ManyToOne({ entity: () => Teacher, primary: true }) + @ManyToOne({ + entity: () => { + return Teacher; + }, + primary: true, + }) author!: Teacher; - @ManyToOne({ entity: () => Question, primary: true }) + @ManyToOne({ + entity: () => { + return Question; + }, + primary: true, + }) toQuestion!: Question; @PrimaryKey({ type: 'integer' }) diff --git a/backend/src/entities/questions/question.entity.ts b/backend/src/entities/questions/question.entity.ts index 67efdfe7..689b6ca1 100644 --- a/backend/src/entities/questions/question.entity.ts +++ b/backend/src/entities/questions/question.entity.ts @@ -3,12 +3,21 @@ import { Language } from '../content/language.js'; import { Student } from '../users/student.entity.js'; import { QuestionRepository } from '../../data/questions/question-repository.js'; -@Entity({ repository: () => QuestionRepository }) +@Entity({ + repository: () => { + return QuestionRepository; + }, +}) export class Question { @PrimaryKey({ type: 'string' }) learningObjectHruid!: string; - @Enum({ items: () => Language, primary: true }) + @Enum({ + items: () => { + return Language; + }, + primary: true, + }) learningObjectLanguage!: Language; @PrimaryKey({ type: 'string' }) @@ -17,7 +26,11 @@ export class Question { @PrimaryKey({ type: 'integer' }) sequenceNumber!: number; - @ManyToOne({ entity: () => Student }) + @ManyToOne({ + entity: () => { + return Student; + }, + }) author!: Student; @Property({ type: 'datetime' }) diff --git a/backend/src/entities/users/student.entity.ts b/backend/src/entities/users/student.entity.ts index 401b1ed2..7ad8c9b3 100644 --- a/backend/src/entities/users/student.entity.ts +++ b/backend/src/entities/users/student.entity.ts @@ -4,11 +4,19 @@ import { Class } from '../classes/class.entity.js'; import { Group } from '../assignments/group.entity.js'; import { StudentRepository } from '../../data/users/student-repository.js'; -@Entity({ repository: () => StudentRepository }) +@Entity({ + repository: () => { + return StudentRepository; + }, +}) export class Student extends User { - @ManyToMany(() => Class) + @ManyToMany(() => { + return Class; + }) classes!: Collection; - @ManyToMany(() => Group) + @ManyToMany(() => { + return Group; + }) groups!: Collection; } diff --git a/backend/src/entities/users/teacher.entity.ts b/backend/src/entities/users/teacher.entity.ts index d53ca603..52cc9f7b 100644 --- a/backend/src/entities/users/teacher.entity.ts +++ b/backend/src/entities/users/teacher.entity.ts @@ -3,8 +3,14 @@ import { User } from './user.entity.js'; import { Class } from '../classes/class.entity.js'; import { TeacherRepository } from '../../data/users/teacher-repository.js'; -@Entity({ repository: () => TeacherRepository }) +@Entity({ + repository: () => { + return TeacherRepository; + }, +}) export class Teacher extends User { - @ManyToMany(() => Class) + @ManyToMany(() => { + return Class; + }) classes!: Collection; } diff --git a/backend/src/interfaces/assignment.ts b/backend/src/interfaces/assignment.ts index 146a0517..ad6d8330 100644 --- a/backend/src/interfaces/assignment.ts +++ b/backend/src/interfaces/assignment.ts @@ -1,14 +1,14 @@ -import { Assignment } from "../entities/assignments/assignment.entity.js"; -import { GroupDTO, mapToGroupDTO } from "./groups.js"; +import { Assignment } from '../entities/assignments/assignment.entity.js'; +import { GroupDTO, mapToGroupDTO } from './group.js'; export interface AssignmentDTO { - id: number, - class: string, // id of class 'within' - title: string, - description: string, - learningPath: string, - language: string, - groups?: GroupDTO[] | string[], // TODO + id: number; + class: string; // Id of class 'within' + title: string; + description: string; + learningPath: string; + language: string; + groups?: GroupDTO[] | string[]; // TODO } export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { @@ -19,8 +19,8 @@ export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { description: assignment.description, learningPath: assignment.learningPathHruid, language: assignment.learningPathLanguage, - // groups: assignment.groups.map(group => group.groupNumber), - } + // Groups: assignment.groups.map(group => group.groupNumber), + }; } export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO { @@ -31,6 +31,6 @@ export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO { description: assignment.description, learningPath: assignment.learningPathHruid, language: assignment.learningPathLanguage, - // groups: assignment.groups.map(mapToGroupDTO), + // Groups: assignment.groups.map(mapToGroupDTO), }; } diff --git a/backend/src/interfaces/class.ts b/backend/src/interfaces/class.ts index 0274d90c..c18ee842 100644 --- a/backend/src/interfaces/class.ts +++ b/backend/src/interfaces/class.ts @@ -1,4 +1,4 @@ -import { Class } from "../entities/classes/class.entity.js"; +import { Class } from '../entities/classes/class.entity.js'; export interface ClassDTO { id: string; @@ -18,8 +18,12 @@ export function mapToClassDTO(cls: Class): ClassDTO { return { id: cls.classId, displayName: cls.displayName, - teachers: cls.teachers.map(teacher => teacher.username), - students: cls.students.map(student => student.username), + teachers: cls.teachers.map((teacher) => { + return teacher.username; + }), + students: cls.students.map((student) => { + return student.username; + }), joinRequests: [], // TODO - } -}; + }; +} diff --git a/backend/src/interfaces/group.ts b/backend/src/interfaces/group.ts index c4c95baf..9c4cecdc 100644 --- a/backend/src/interfaces/group.ts +++ b/backend/src/interfaces/group.ts @@ -1,25 +1,27 @@ -import { Group } from "../entities/assignments/group.entity.js"; -import { AssignmentDTO, mapToAssignmentDTO } from "./assignments.js"; -import { mapToStudentDTO, StudentDTO } from "./students.js"; +import { Group } from '../entities/assignments/group.entity.js'; +import { AssignmentDTO, mapToAssignmentDTO } from './assignment.js'; +import { mapToStudentDTO, StudentDTO } from './student.js'; export interface GroupDTO { - assignment: number | AssignmentDTO, - groupNumber: number, - members: string[] | StudentDTO[], -}; + assignment: number | AssignmentDTO; + groupNumber: number; + members: string[] | StudentDTO[]; +} export function mapToGroupDTO(group: Group): GroupDTO { return { assignment: mapToAssignmentDTO(group.assignment), // ERROR: , group.assignment.within), groupNumber: group.groupNumber, members: group.members.map(mapToStudentDTO), - } + }; } export function mapToGroupDTOId(group: Group): GroupDTO { return { assignment: group.assignment.id, groupNumber: group.groupNumber, - members: group.members.map(member => member.username), - } + members: group.members.map((member) => { + return member.username; + }), + }; } diff --git a/backend/src/interfaces/list.ts b/backend/src/interfaces/list.ts index 0037403d..6892fb9d 100644 --- a/backend/src/interfaces/list.ts +++ b/backend/src/interfaces/list.ts @@ -1,5 +1,5 @@ // TODO: implement something like this but with named endpoints export interface List { - items: T[], - endpoints?: string[], -}; \ No newline at end of file + items: T[]; + endpoints?: string[]; +} diff --git a/backend/src/interfaces/question.ts b/backend/src/interfaces/question.ts index 1a8c914a..90de4999 100644 --- a/backend/src/interfaces/question.ts +++ b/backend/src/interfaces/question.ts @@ -1,6 +1,4 @@ -import {Question} from "../entities/questions/question.entity"; -import {Enum, PrimaryKey} from "@mikro-orm/core"; -import {Language} from "../entities/content/language"; +import { Question } from '../entities/questions/question.entity.js'; export interface QuestionDTO { learningObjectHruid: string; @@ -34,8 +32,17 @@ export function mapToQuestionDTO(question: Question): QuestionDTO { } export interface QuestionId { - learningObjectHruid: string, - learningObjectLanguage: Language, - learningObjectVersion: string, - sequenceNumber: number + learningObjectHruid: string; + learningObjectLanguage: string; + learningObjectVersion: string; + sequenceNumber: number; +} + +export function mapToQuestionId(question: QuestionDTO): QuestionId { + return { + learningObjectHruid: question.learningObjectHruid, + learningObjectLanguage: question.learningObjectLanguage, + learningObjectVersion: question.learningObjectVersion, + sequenceNumber: question.sequenceNumber, + }; } diff --git a/backend/src/interfaces/student.ts b/backend/src/interfaces/student.ts index c18461e8..529c6ead 100644 --- a/backend/src/interfaces/student.ts +++ b/backend/src/interfaces/student.ts @@ -1,4 +1,4 @@ -import { Student } from "../entities/users/student.entity.js"; +import { Student } from '../entities/users/student.entity.js'; export interface StudentDTO { id: string; diff --git a/backend/src/interfaces/teacher-invitation.ts b/backend/src/interfaces/teacher-invitation.ts index 489e5565..badbbbd7 100644 --- a/backend/src/interfaces/teacher-invitation.ts +++ b/backend/src/interfaces/teacher-invitation.ts @@ -1,22 +1,26 @@ -import { TeacherInvitation } from "../entities/classes/teacher-invitation.entity.js"; -import { ClassDTO, mapToClassDTO } from "./classes.js"; -import { mapToTeacherDTO, TeacherDTO } from "./teacher.js"; +import { TeacherInvitation } from '../entities/classes/teacher-invitation.entity.js'; +import { ClassDTO, mapToClassDTO } from './class.js'; +import { mapToUserDTO, UserDTO } from './user.js'; export interface TeacherInvitationDTO { - sender: string | TeacherDTO, - receiver: string | TeacherDTO, - class: string | ClassDTO, + sender: string | UserDTO; + receiver: string | UserDTO; + class: string | ClassDTO; } -export function mapToTeacherInvitationDTO(invitation: TeacherInvitation): TeacherInvitationDTO { +export function mapToTeacherInvitationDTO( + invitation: TeacherInvitation +): TeacherInvitationDTO { return { - sender: mapToTeacherDTO(invitation.sender), - receiver: mapToTeacherDTO(invitation.receiver), + sender: mapToUserDTO(invitation.sender), + receiver: mapToUserDTO(invitation.receiver), class: mapToClassDTO(invitation.class), }; } -export function mapToTeacherInvitationDTOIds(invitation: TeacherInvitation): TeacherInvitationDTO { +export function mapToTeacherInvitationDTOIds( + invitation: TeacherInvitation +): TeacherInvitationDTO { return { sender: invitation.sender.username, receiver: invitation.receiver.username, diff --git a/backend/src/interfaces/teacher.ts b/backend/src/interfaces/teacher.ts deleted file mode 100644 index 15c89520..00000000 --- a/backend/src/interfaces/teacher.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Teacher } from "../entities/users/teacher.entity.js"; - -/** - * Teacher Data Transfer Object - */ -export interface TeacherDTO { - username: string; - firstName: string; - lastName: string; - endpoints?: { - self: string; - classes: string; - questions: string; - invitations: string; - }; -} - -/** - * Maps a Teacher entity to a TeacherDTO - */ -export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { - return { - username: teacher.username, - firstName: teacher.firstName, - lastName: teacher.lastName, - }; -} - -export function mapToTeacher(teacherData: TeacherDTO): Teacher { - const teacher = new Teacher(); - teacher.username = teacherData.username; - teacher.firstName = teacherData.firstName; - teacher.lastName = teacherData.lastName; - - return teacher; -} diff --git a/backend/src/interfaces/user.ts b/backend/src/interfaces/user.ts index 02e27d83..64081d48 100644 --- a/backend/src/interfaces/user.ts +++ b/backend/src/interfaces/user.ts @@ -1,7 +1,7 @@ -import { User } from "../entities/users/user.entity.js"; +import { User } from '../entities/users/user.entity.js'; export interface UserDTO { - id?: string, + id?: string; username: string; firstName: string; lastName: string; @@ -22,7 +22,10 @@ export function mapToUserDTO(user: User): UserDTO { }; } -export function mapToUser(userData: UserDTO, userInstance: T): T { +export function mapToUser( + userData: UserDTO, + userInstance: T +): T { userInstance.username = userData.username; userInstance.firstName = userData.firstName; userInstance.lastName = userData.lastName; diff --git a/backend/src/mikro-orm.config.ts b/backend/src/mikro-orm.config.ts index 6af867e9..05b68fef 100644 --- a/backend/src/mikro-orm.config.ts +++ b/backend/src/mikro-orm.config.ts @@ -24,11 +24,20 @@ import { Answer } from './entities/questions/answer.entity.js'; import { Question } from './entities/questions/question.entity.js'; const entities = [ - User, Student, Teacher, - Assignment, Group, Submission, - Class, ClassJoinRequest, TeacherInvitation, - Attachment, LearningObject, LearningPath, - Answer, Question + User, + Student, + Teacher, + Assignment, + Group, + Submission, + Class, + ClassJoinRequest, + TeacherInvitation, + Attachment, + LearningObject, + LearningPath, + Answer, + Question, ]; function config(testingMode: boolean = false): Options { @@ -37,25 +46,26 @@ function config(testingMode: boolean = false): Options { driver: SqliteDriver, dbName: getEnvVar(EnvVars.DbName), entities: entities, - // entitiesTs: entitiesTs, + // EntitiesTs: entitiesTs, // Workaround: vitest: `TypeError: Unknown file extension ".ts"` (ERR_UNKNOWN_FILE_EXTENSION) // (see https://mikro-orm.io/docs/guide/project-setup#testing-the-endpoint) - dynamicImportProvider: (id) => import(id), - }; - } else { - return { - driver: PostgreSqlDriver, - host: getEnvVar(EnvVars.DbHost), - port: getNumericEnvVar(EnvVars.DbPort), - dbName: getEnvVar(EnvVars.DbName), - user: getEnvVar(EnvVars.DbUsername), - password: getEnvVar(EnvVars.DbPassword), - entities: entities, - //entitiesTs: entitiesTs, - debug: true, + dynamicImportProvider: (id) => { + return import(id); + }, }; } + return { + driver: PostgreSqlDriver, + host: getEnvVar(EnvVars.DbHost), + port: getNumericEnvVar(EnvVars.DbPort), + dbName: getEnvVar(EnvVars.DbName), + user: getEnvVar(EnvVars.DbUsername), + password: getEnvVar(EnvVars.DbPassword), + entities: entities, + //EntitiesTs: entitiesTs, + debug: true, + }; } export default config; diff --git a/backend/src/routes/assignments.ts b/backend/src/routes/assignments.ts index 9d83e755..85f3bc82 100644 --- a/backend/src/routes/assignments.ts +++ b/backend/src/routes/assignments.ts @@ -1,31 +1,30 @@ -import express from 'express' -import { getAllAssignmentsHandler, getAssignmentHandler } from '../controllers/assignments.js'; -import groupRouter from './group.js'; +import express from 'express'; +import { + getAllAssignmentsHandler, + getAssignmentHandler, +} from '../controllers/assignments.js'; +import groupRouter from './groups.js'; const router = express.Router({ mergeParams: true }); -// root endpoint used to search objects +// Root endpoint used to search objects router.get('/', getAllAssignmentsHandler); -// information about an assignment with id 'id' +// Information about an assignment with id 'id' router.get('/:id', getAssignmentHandler); router.get('/:id/submissions', (req, res) => { res.json({ - submissions: [ - '0' - ], + submissions: ['0'], }); }); router.get('/:id/questions', (req, res) => { res.json({ - questions: [ - '0' - ], + questions: ['0'], }); }); router.use('/:assignmentid/groups', groupRouter); -export default router +export default router; diff --git a/backend/src/routes/classes.ts b/backend/src/routes/classes.ts index 06154e60..c67b573b 100644 --- a/backend/src/routes/classes.ts +++ b/backend/src/routes/classes.ts @@ -1,13 +1,18 @@ -import express from 'express' -import { getAllClassesHandler, getClassHandler, getClassStudentsHandler, getTeacherInvitationsHandler } from '../controllers/classes.js'; -import assignmentRouter from './assignment.js'; +import express from 'express'; +import { + getAllClassesHandler, + getClassHandler, + getClassStudentsHandler, + getTeacherInvitationsHandler, +} from '../controllers/classes.js'; +import assignmentRouter from './assignments.js'; const router = express.Router(); -// root endpoint used to search objects +// Root endpoint used to search objects router.get('/', getAllClassesHandler); -// information about an class with id 'id' +// Information about an class with id 'id' router.get('/:id', getClassHandler); router.get('/:id/teacher-invitations', getTeacherInvitationsHandler); @@ -16,4 +21,4 @@ router.get('/:id/students', getClassStudentsHandler); router.use('/:classid/assignments', assignmentRouter); -export default router +export default router; diff --git a/backend/src/routes/groups.ts b/backend/src/routes/groups.ts index 76cdc61f..d604c088 100644 --- a/backend/src/routes/groups.ts +++ b/backend/src/routes/groups.ts @@ -1,18 +1,19 @@ -import express from 'express' +import express from 'express'; import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups.js'; + const router = express.Router({ mergeParams: true }); -// root endpoint used to search objects +// Root endpoint used to search objects router.get('/', getAllGroupsHandler); -// information about a group (members, ... [TODO DOC]) +// Information about a group (members, ... [TODO DOC]) router.get('/:groupid', getGroupHandler); -// the list of questions a group has made +// The list of questions a group has made router.get('/:id/question', (req, res) => { res.json({ - questions: [ '0' ], + questions: ['0'], }); -}) +}); -export default router +export default router; diff --git a/backend/src/routes/questions.ts b/backend/src/routes/questions.ts index 25d168b7..f683d998 100644 --- a/backend/src/routes/questions.ts +++ b/backend/src/routes/questions.ts @@ -1,38 +1,34 @@ -import express from 'express' +import express from 'express'; const router = express.Router(); -// root endpoint used to search objects +// Root endpoint used to search objects router.get('/', (req, res) => { res.json({ - questions: [ - '0', - '1', - ] + questions: ['0', '1'], }); }); -// information about an question with id 'id' +// Information about an question with id 'id' router.get('/:id', (req, res) => { res.json({ id: req.params.id, student: '0', group: '0', time: new Date(2025, 1, 1), - content: 'Zijn alle gehele getallen groter dan 2 gelijk aan de som van 2 priemgetallen????', + content: + 'Zijn alle gehele getallen groter dan 2 gelijk aan de som van 2 priemgetallen????', learningObject: '0', links: { self: `${req.baseUrl}/${req.params.id}`, answers: `${req.baseUrl}/${req.params.id}/answers`, - } + }, }); -}) +}); router.get('/:id/answers', (req, res) => { res.json({ - answers: [ - '0' - ], - }) -}) + answers: ['0'], + }); +}); -export default router \ No newline at end of file +export default router; diff --git a/backend/src/routes/students.ts b/backend/src/routes/students.ts index a5355c48..da1c4308 100644 --- a/backend/src/routes/students.ts +++ b/backend/src/routes/students.ts @@ -1,51 +1,49 @@ -import express from 'express' +import express from 'express'; import { - createStudentHandler, deleteStudentHandler, + createStudentHandler, + deleteStudentHandler, getAllStudentsHandler, getStudentAssignmentsHandler, getStudentClassesHandler, - getStudentHandler + getStudentHandler, } from '../controllers/students.js'; const router = express.Router(); -// root endpoint used to search objects +// Root endpoint used to search objects router.get('/', getAllStudentsHandler); router.post('/', createStudentHandler); router.delete('/:username', deleteStudentHandler); -// information about a student's profile +// Information about a student's profile router.get('/:username', getStudentHandler); - - -// the list of classes a student is in +// The list of classes a student is in router.get('/:id/classes', getStudentClassesHandler); -// the list of submissions a student has made +// The list of submissions a student has made router.get('/:id/submissions', (req, res) => { res.json({ - submissions: [ '0' ], + submissions: ['0'], }); -}) +}); - -// the list of assignments a student has +// The list of assignments a student has router.get('/:id/assignments', getStudentAssignmentsHandler); -// the list of groups a student is in +// The list of groups a student is in router.get('/:id/groups', (req, res) => { res.json({ - groups: [ '0' ], + groups: ['0'], }); -}) +}); -// a list of questions a user has created +// A list of questions a user has created router.get('/:id/questions', (req, res) => { res.json({ - questions: [ '0' ], + questions: ['0'], }); -}) +}); -export default router +export default router; diff --git a/backend/src/routes/submissions.ts b/backend/src/routes/submissions.ts index 8d09cf8e..cb4d3e85 100644 --- a/backend/src/routes/submissions.ts +++ b/backend/src/routes/submissions.ts @@ -1,17 +1,14 @@ -import express from 'express' +import express from 'express'; const router = express.Router(); -// root endpoint used to search objects +// Root endpoint used to search objects router.get('/', (req, res) => { res.json({ - submissions: [ - '0', - '1', - ] + submissions: ['0', '1'], }); }); -// information about an submission with id 'id' +// Information about an submission with id 'id' router.get('/:id', (req, res) => { res.json({ id: req.params.id, @@ -21,6 +18,6 @@ router.get('/:id', (req, res) => { content: 'Wortel 2 is rationeel', learningObject: '0', }); -}) +}); -export default router \ No newline at end of file +export default router; diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index 2a29897b..8e7f709d 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -1,17 +1,22 @@ -import express from 'express' +import express from 'express'; import { createTeacherHandler, deleteTeacherHandler, + getAllTeachersHandler, getTeacherClassHandler, - getTeacherHandler, getTeacherQuestionHandler, getTeacherStudentHandler -} from "../controllers/teachers.js"; + getTeacherHandler, + getTeacherQuestionHandler, + getTeacherStudentHandler, +} from '../controllers/teachers.js'; const router = express.Router(); -// root endpoint used to search objects -router.get('/', getTeacherHandler); +// Root endpoint used to search objects +router.get('/', getAllTeachersHandler); router.post('/', createTeacherHandler); +router.get('/:username', getTeacherHandler); + router.delete('/:username', deleteTeacherHandler); router.get('/:username/classes', getTeacherClassHandler); @@ -20,15 +25,11 @@ router.get('/:username/students', getTeacherStudentHandler); router.get('/:username/questions', getTeacherQuestionHandler); -// invitations to other classes a teacher received +// Invitations to other classes a teacher received router.get('/:id/invitations', (req, res) => { res.json({ - invitations: [ - '0' - ], + invitations: ['0'], }); }); - - -export default router +export default router; diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index aaa51c10..1ecfb4d4 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -1,7 +1,17 @@ -import { getAssignmentRepository, getClassRepository } from "../data/repositories.js"; -import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId } from "../interfaces/assignments.js"; +import { + getAssignmentRepository, + getClassRepository, +} from '../data/repositories.js'; +import { + AssignmentDTO, + mapToAssignmentDTO, + mapToAssignmentDTOId, +} from '../interfaces/assignment.js'; -export async function getAllAssignments(classid: string, full: boolean): Promise { +export async function getAllAssignments( + classid: string, + full: boolean +): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classid); @@ -10,7 +20,8 @@ export async function getAllAssignments(classid: string, full: boolean): Promise } const assignmentRepository = getAssignmentRepository(); - const assignments = await assignmentRepository.findAllAssignmentsInClass(cls); + const assignments = + await assignmentRepository.findAllAssignmentsInClass(cls); if (full) { return assignments.map(mapToAssignmentDTO); @@ -19,7 +30,10 @@ export async function getAllAssignments(classid: string, full: boolean): Promise return assignments.map(mapToAssignmentDTOId); } -export async function getAssignment(classid: string, id: number): Promise { +export async function getAssignment( + classid: string, + id: number +): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classid); diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 3867d910..a26aa7c2 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -1,11 +1,23 @@ -import { getClassRepository } from "../data/repositories"; -import { Class } from "../entities/classes/class.entity"; -import { ClassDTO, mapToClassDTO } from "../interfaces/class"; -import { mapToStudentDTO, StudentDTO } from "../interfaces/student"; +import { + getClassRepository, + getTeacherInvitationRepository, +} from '../data/repositories.js'; +import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; +import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; +import { + mapToTeacherInvitationDTO, + mapToTeacherInvitationDTOIds, + TeacherInvitationDTO, +} from '../interfaces/teacher-invitation.js'; -export async function getAllClasses(full: boolean): Promise { +export async function getAllClasses( + full: boolean +): Promise { const classRepository = getClassRepository(); - const classes = await classRepository.find({}, { populate: ["students", "teachers"] }); + const classes = await classRepository.find( + {}, + { populate: ['students', 'teachers'] } + ); if (!classes) { return []; @@ -13,27 +25,30 @@ export async function getAllClasses(full: boolean): Promise cls.classId); } + return classes.map((cls) => { + return cls.classId; + }); } export async function getClass(classId: string): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); - if (!cls) return null; - else { - return mapToClassDTO(cls); + if (!cls) { + return null; } + + return mapToClassDTO(cls); } -async function fetchClassStudents(classId: string, full: boolean): Promise { +async function fetchClassStudents(classId: string): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); - if (!cls) + if (!cls) { return []; + } return cls.students.map(mapToStudentDTO); } @@ -43,6 +58,36 @@ export async function getClassStudents(classId: string): Promise { } export async function getClassStudentsIds(classId: string): Promise { - return await fetchClassStudents(classId).map((student) => student.username); + const students: StudentDTO[] = await fetchClassStudents(classId); + return students.map((student) => { + return student.username; + }); } +export async function getClassTeacherInvitations( + classId: string, + full: boolean +): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classId); + + if (!cls) { + return []; + } + + const teacherInvitationRepository = getTeacherInvitationRepository(); + const invitations = + await teacherInvitationRepository.findAllInvitationsForClass(cls); + + console.log(invitations); + + if (!invitations) { + return []; + } + + if (full) { + return invitations.map(mapToTeacherInvitationDTO); + } + + return invitations.map(mapToTeacherInvitationDTOIds); +} diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index b37c7c5c..467f90a3 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -1,11 +1,19 @@ -import { getAssignmentRepository, getClassRepository, getGroupRepository } from "../data/repositories.js"; -import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from "../interfaces/groups.js"; +import { + getAssignmentRepository, + getClassRepository, + getGroupRepository, +} from '../data/repositories.js'; +import { + GroupDTO, + mapToGroupDTO, + mapToGroupDTOId, +} from '../interfaces/group.js'; export async function getGroup( classId: string, assignmentNumber: number, groupNumber: number, - full: boolean, + full: boolean ): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); @@ -15,14 +23,20 @@ export async function getGroup( } const assignmentRepository = getAssignmentRepository(); - const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); + const assignment = await assignmentRepository.findByClassAndId( + cls, + assignmentNumber + ); if (!assignment) { return null; } const groupRepository = getGroupRepository(); - const group = await groupRepository.findByAssignmentAndGroupNumber(assignment, groupNumber); + const group = await groupRepository.findByAssignmentAndGroupNumber( + assignment, + groupNumber + ); if (!group) { return null; @@ -38,7 +52,7 @@ export async function getGroup( export async function getAllGroups( classId: string, assignmentNumber: number, - full: boolean, + full: boolean ): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); @@ -48,7 +62,10 @@ export async function getAllGroups( } const assignmentRepository = getAssignmentRepository(); - const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); + const assignment = await assignmentRepository.findByClassAndId( + cls, + assignmentNumber + ); if (!assignment) { return []; diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 24c9029b..952c3cf1 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,8 +1,11 @@ -import { getClassRepository, getStudentRepository } from "../data/repositories.js"; -import { Class } from "../entities/classes/class.entity.js"; -import { Student } from "../entities/users/student.entity.js"; -import { ClassDTO, mapToClassDTO } from "../interfaces/classes.js"; -import {UserService} from "./users.js"; +import { + getClassRepository, + getStudentRepository, +} from '../data/repositories.js'; +import { Class } from '../entities/classes/class.entity.js'; +import { Student } from '../entities/users/student.entity.js'; +import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; +import { UserService } from './users.js'; export class StudentService extends UserService { constructor() { @@ -14,12 +17,16 @@ async function fetchStudentClasses(username: string): Promise { const studentRepository = getStudentRepository(); const student = await studentRepository.findByUsername(username); - if (!student) return []; + if (!student) { + return []; + } const classRepository = getClassRepository(); const classes = await classRepository.findByStudent(student); - if (!classes) return []; + if (!classes) { + return []; + } return classes; } @@ -31,6 +38,7 @@ export async function getStudentClasses(username: string): Promise { export async function getStudentClassIds(username: string): Promise { const classes = await fetchStudentClasses(username); - return classes.map(cls => cls.classId); // 'class' is a native keyword + return classes.map((cls) => { + return cls.classId; + }); // 'class' is a native keyword } - diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 4b8affc5..b87c3b92 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -2,130 +2,108 @@ import { getClassRepository, getLearningObjectRepository, getQuestionRepository, - getTeacherRepository -} from "../data/repositories.js"; -import {mapToTeacher, mapToTeacherDTO, TeacherDTO} from "../interfaces/teacher.js"; -import { Teacher } from "../entities/users/teacher.entity"; -import {ClassDTO, mapToClassDTO} from "../interfaces/class"; -import {getClassStudents, getClassStudentsIds} from "./class"; -import {StudentDTO} from "../interfaces/student"; -import {mapToQuestionDTO, QuestionDTO, QuestionId} from "../interfaces/question"; + getStudentRepository, + getTeacherRepository, +} from '../data/repositories.js'; +import { Teacher } from '../entities/users/teacher.entity.js'; +import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; +import { getClassStudents } from './class.js'; +import { StudentDTO } from '../interfaces/student.js'; +import { + mapToQuestionDTO, + mapToQuestionId, + QuestionDTO, + QuestionId, +} from '../interfaces/question.js'; +import { UserService } from './users.js'; +import { mapToUser } from '../interfaces/user.js'; - -async function fetchAllTeachers(): Promise { - const teacherRepository = getTeacherRepository(); - const teachers = await teacherRepository.find({}); - - return teachers.map(mapToTeacherDTO); +export class TeacherUserService extends UserService { + constructor() { + super(getTeacherRepository()); + } } -export async function getAllTeachers(): Promise { - return await fetchAllTeachers(); -} +export class TeacherService { + protected teacherService = new TeacherUserService(); + protected teacherRepository = getTeacherRepository(); + protected classRepository = getClassRepository(); + protected learningObjectRepository = getLearningObjectRepository(); + protected questionRepository = getQuestionRepository(); -export async function getAllTeachersIds(): Promise { - return await fetchAllTeachers().map((teacher) => teacher.username) -} + async fetchClassesByTeacher(username: string): Promise { + const teacher = await this.teacherRepository.findByUsername(username); + if (!teacher) { + return []; + } -export async function createTeacher(teacherData: TeacherDTO): Promise { - const teacherRepository = getTeacherRepository(); - const newTeacher = mapToTeacher(teacherData); - - await teacherRepository.addTeacher(newTeacher); - return newTeacher; -} - -export async function getTeacherByUsername(username: string): Promise { - const teacherRepository = getTeacherRepository(); - const teacher = await teacherRepository.findByUsername(username); - - return teacher ? mapToTeacherDTO(teacher) : null; -} - -export async function deleteTeacher(username: string): Promise { - const teacherRepository = getTeacherRepository(); - const teacher = await teacherRepository.findByUsername(username); - - if (!teacher) - return null; - - await teacherRepository.deleteByUsername(username); - return teacher; -} - -async function fetchClassesByTeacher(username: string): Promise { - const teacherRepository = getTeacherRepository(); - const classRepository = getClassRepository(); - - const teacher = await teacherRepository.findByUsername(username); - if (!teacher) { - return []; + const classes = await this.classRepository.findByTeacher(teacher); + return classes.map(mapToClassDTO); } - const classes = await classRepository.findByTeacher(teacher); - return classes.map(mapToClassDTO); -} - -export async function getClassesByTeacher(username: string): Promise { - return await fetchClassesByTeacher(username) -} - -export async function getClassIdsByTeacher(): Promise { - return await fetchClassesByTeacher(username).map((cls) => cls.id); -} - -async function fetchStudentsByTeacher(username: string) { - const classes = await getClassIdsByTeacher(); - - return Promise.all( - classes.map( async (id) => getClassStudents(id)) - ); -} - -export async function getStudentsByTeacher(username: string): Promise { - return await fetchStudentsByTeacher(username); -} - -export async function getStudentIdsByTeacher(): Promise { - return await fetchStudentsByTeacher(username).map((student) => student.username); -} - -async function fetchTeacherQuestions(username: string): Promise { - const learningObjectRepository = getLearningObjectRepository(); - const questionRepository = getQuestionRepository(); - - const teacher = getTeacherByUsername(username); - if (!teacher) { - throw new Error(`Teacher with username '${username}' not found.`); + async getClassesByTeacher(username: string): Promise { + return await this.fetchClassesByTeacher(username); } - // Find all learning objects that this teacher manages - const learningObjects = await learningObjectRepository.findAllByTeacher(teacher); + async getClassIdsByTeacher(username: string): Promise { + const classes = await this.fetchClassesByTeacher(username); + return classes.map((cls) => { + return cls.id; + }); + } - // Fetch all questions related to these learning objects - const questions = await questionRepository.findAllByLearningObjects(learningObjects); + async fetchStudentsByTeacher(username: string) { + const classes = await this.getClassIdsByTeacher(username); - return questions.map(mapToQuestionDTO); + return ( + await Promise.all( + classes.map(async (id) => { + return getClassStudents(id); + }) + ) + ).flat(); + } + + async getStudentsByTeacher(username: string): Promise { + return await this.fetchStudentsByTeacher(username); + } + + async getStudentIdsByTeacher(username: string): Promise { + const students = await this.fetchStudentsByTeacher(username); + return students.map((student) => { + return student.username; + }); + } + + async fetchTeacherQuestions(username: string): Promise { + const teacherDTO = + await this.teacherService.getUserByUsername(username); + if (!teacherDTO) { + throw new Error(`Teacher with username '${username}' not found.`); + } + + const teacher = mapToUser(teacherDTO, new Teacher()); + + // Find all learning objects that this teacher manages + const learningObjects = + await this.learningObjectRepository.findAllByTeacher(teacher); + + // Fetch all questions related to these learning objects + const questions = + await this.questionRepository.findAllByLearningObjects( + learningObjects + ); + + return questions.map(mapToQuestionDTO); + } + + async getQuestionsByTeacher(username: string): Promise { + return await this.fetchTeacherQuestions(username); + } + + async getQuestionIdsByTeacher(username: string): Promise { + const questions = await this.fetchTeacherQuestions(username); + + return questions.map(mapToQuestionId); + } } - -export async function getQuestionsByTeacher(username: string): Promise { - return await fetchTeacherQuestions(username); -} - -export async function getQuestionIdsByTeacher(username: string): Promise { - const questions = await fetchTeacherQuestions(username); - - return questions.map((question) => ({ - learningObjectHruid: question.learningObjectHruid, - learningObjectLanguage: question.learningObjectLanguage, - learningObjectVersion: question.learningObjectVersion, - sequenceNumber: question.sequenceNumber - })); -} - - - - - - - diff --git a/backend/src/services/users.ts b/backend/src/services/users.ts index bf88e916..fc1ea599 100644 --- a/backend/src/services/users.ts +++ b/backend/src/services/users.ts @@ -1,6 +1,6 @@ -import { UserRepository } from "../data/users/user-repository.js"; -import { UserDTO, mapToUser, mapToUserDTO } from "../interfaces/user.js"; -import {User} from "../entities/users/user.entity.js"; +import { UserRepository } from '../data/users/user-repository.js'; +import { UserDTO, mapToUser, mapToUserDTO } from '../interfaces/user.js'; +import { User } from '../entities/users/user.entity.js'; export class UserService { protected repository: UserRepository; @@ -16,11 +16,13 @@ export class UserService { async getAllUserIds(): Promise { const users = await this.getAllUsers(); - return users.map((user) => user.username); + return users.map((user) => { + return user.username; + }); } async getUserByUsername(username: string): Promise { - const user = await this.repository.findByUsername(username) + const user = await this.repository.findByUsername(username); return user ? mapToUserDTO(user) : null; } @@ -32,8 +34,10 @@ export class UserService { async deleteUser(username: string): Promise { const user = await this.getUserByUsername(username); - if (!user) return null; - await this.repository.deleteByUsername(username) + if (!user) { + return null; + } + await this.repository.deleteByUsername(username); return mapToUserDTO(user); } } diff --git a/backend/src/util/translation-helper.ts b/backend/src/util/translation-helper.ts index d6d842ff..f02a3a1b 100644 --- a/backend/src/util/translation-helper.ts +++ b/backend/src/util/translation-helper.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import yaml from 'js-yaml'; -import { FALLBACK_LANG } from "../config.js"; +import { FALLBACK_LANG } from '../config.js'; export function loadTranslations(language: string): T { try { @@ -13,7 +13,11 @@ export function loadTranslations(language: string): T { `Cannot load translation for ${language}, fallen back to dutch` ); console.error(error); - const fallbackPath = path.join(process.cwd(), '_i18n', `${FALLBACK_LANG}.yml`); + const fallbackPath = path.join( + process.cwd(), + '_i18n', + `${FALLBACK_LANG}.yml` + ); return yaml.load(fs.readFileSync(fallbackPath, 'utf8')) as T; } } From 22cdf58fed42109f8ca69a6b62be534d611dd764 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Mon, 10 Mar 2025 11:24:37 +0100 Subject: [PATCH 22/49] feat: groepen van een leerling geimplmenteerd in backend --- backend/src/controllers/students.ts | 34 +++++------ .../src/data/assignments/group-repository.ts | 9 +++ backend/src/services/students.ts | 56 +++++++++++++++---- 3 files changed, 71 insertions(+), 28 deletions(-) diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 2134a9f2..a104979a 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,7 +1,8 @@ import { Request, Response } from 'express'; import { + getStudentAssignments, getStudentClasses, - getStudentClassIds, + getStudentGroups, StudentService, } from '../services/students.js'; import { ClassDTO } from '../interfaces/class.js'; @@ -52,12 +53,7 @@ export async function getStudentClassesHandler( const full = req.query.full === 'true'; const username = req.params.id; - let classes: ClassDTO[] | string[]; - if (full) { - classes = await getStudentClasses(username); - } else { - classes = await getStudentClassIds(username); - } + const classes = await getStudentClasses(username, full); res.json({ classes: classes, @@ -85,17 +81,23 @@ export async function getStudentAssignmentsHandler( const full = req.query.full === 'true'; const username = req.params.id; - const classes = await getStudentClasses(username); - - const assignments = ( - await Promise.all( - classes.map(async (cls) => { - return await getAllAssignments(cls.id, full); - }) - ) - ).flat(); + const assignments = getStudentAssignments(username, full); res.json({ assignments: assignments, }); } + +export async function getStudentGroupsHandler( + req: Request, + res: Response, +): Promise { + const full = req.query.full === 'true'; + const username = req.params.id; + + const groups = await getStudentGroups(username, full); + + res.json({ + groups: groups, + }); +} diff --git a/backend/src/data/assignments/group-repository.ts b/backend/src/data/assignments/group-repository.ts index e9b668b9..56736787 100644 --- a/backend/src/data/assignments/group-repository.ts +++ b/backend/src/data/assignments/group-repository.ts @@ -1,6 +1,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Group } from '../../entities/assignments/group.entity.js'; import { Assignment } from '../../entities/assignments/assignment.entity.js'; +import { Student } from '../../entities/users/student.entity.js'; export class GroupRepository extends DwengoEntityRepository { public findByAssignmentAndGroupNumber( @@ -23,6 +24,14 @@ export class GroupRepository extends DwengoEntityRepository { populate: ['members'], }); } + public findAllGroupsWithStudent( + student: Student + ): Promise { + return this.find( + { members: student }, + { populate: ['members'] } + ) + } public deleteByAssignmentAndGroupNumber( assignment: Assignment, groupNumber: number diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 952c3cf1..fc0a8e1d 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,10 +1,14 @@ import { getClassRepository, + getGroupRepository, getStudentRepository, } from '../data/repositories.js'; import { Class } from '../entities/classes/class.entity.js'; import { Student } from '../entities/users/student.entity.js'; +import { AssignmentDTO } from '../interfaces/assignment.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; +import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; +import { getAllAssignments } from './assignments.js'; import { UserService } from './users.js'; export class StudentService extends UserService { @@ -13,7 +17,7 @@ export class StudentService extends UserService { } } -async function fetchStudentClasses(username: string): Promise { +export async function getStudentClasses(username: string, full: boolean): Promise { const studentRepository = getStudentRepository(); const student = await studentRepository.findByUsername(username); @@ -24,21 +28,49 @@ async function fetchStudentClasses(username: string): Promise { const classRepository = getClassRepository(); const classes = await classRepository.findByStudent(student); - if (!classes) { + if (full) { + return classes.map(mapToClassDTO); + } + + return classes.map((cls) => cls.classId); +} + +export async function getStudentAssignments(username: string, full: boolean): Promise { + const studentRepository = getStudentRepository(); + const student = await studentRepository.findByUsername(username); + + if (!student) { return []; } - return classes; + const classRepository = getClassRepository(); + const classes = await classRepository.findByStudent(student); + + const assignments = ( + await Promise.all( + classes.map(async (cls) => { + return await getAllAssignments(cls.classId, full); + }) + ) + ).flat(); + + return assignments; } -export async function getStudentClasses(username: string): Promise { - const classes = await fetchStudentClasses(username); - return classes.map(mapToClassDTO); -} +export async function getStudentGroups(username: string, full: boolean): Promise { + const studentRepository = getStudentRepository(); + const student = await studentRepository.findByUsername(username); -export async function getStudentClassIds(username: string): Promise { - const classes = await fetchStudentClasses(username); - return classes.map((cls) => { - return cls.classId; - }); // 'class' is a native keyword + if (!student) { + return []; + } + + const groupRepository = getGroupRepository(); + const groups = await groupRepository.findAllGroupsWithStudent(student); + + if (full) { + return groups.map(mapToGroupDTO); + } + + return groups.map(mapToGroupDTOId); } From 9f889fa5f149bf9a3ad9fd041305de4f202acfaf Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Mon, 10 Mar 2025 11:27:46 +0100 Subject: [PATCH 23/49] fix: student group handler in routes/student.ts toegevoegd --- backend/src/routes/students.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/backend/src/routes/students.ts b/backend/src/routes/students.ts index da1c4308..c18b3e1c 100644 --- a/backend/src/routes/students.ts +++ b/backend/src/routes/students.ts @@ -5,8 +5,10 @@ import { getAllStudentsHandler, getStudentAssignmentsHandler, getStudentClassesHandler, + getStudentGroupsHandler, getStudentHandler, } from '../controllers/students.js'; +import { getStudentGroups } from '../services/students.js'; const router = express.Router(); // Root endpoint used to search objects @@ -33,11 +35,7 @@ router.get('/:id/submissions', (req, res) => { router.get('/:id/assignments', getStudentAssignmentsHandler); // The list of groups a student is in -router.get('/:id/groups', (req, res) => { - res.json({ - groups: ['0'], - }); -}); +router.get('/:id/groups', getStudentGroupsHandler); // A list of questions a user has created router.get('/:id/questions', (req, res) => { From e9cfa41933f1fa8c5fb0d621e40b82d5acbea778 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 11 Mar 2025 10:42:05 +0100 Subject: [PATCH 24/49] fix: console.log in services/class.ts verwijderd --- backend/src/services/class.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index a26aa7c2..4e010dda 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -79,8 +79,6 @@ export async function getClassTeacherInvitations( const invitations = await teacherInvitationRepository.findAllInvitationsForClass(cls); - console.log(invitations); - if (!invitations) { return []; } From b3299949b02b3b954e70e0d3315f480adf9689e4 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 11 Mar 2025 10:44:20 +0100 Subject: [PATCH 25/49] fix: onnodige null check verwijderd in services/class.ts --- backend/src/services/class.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 4e010dda..45185383 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -79,10 +79,6 @@ export async function getClassTeacherInvitations( const invitations = await teacherInvitationRepository.findAllInvitationsForClass(cls); - if (!invitations) { - return []; - } - if (full) { return invitations.map(mapToTeacherInvitationDTO); } From 7c453467df8dfd0ce8aadc1ce69b50f25af202aa Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 11 Mar 2025 18:04:27 +0100 Subject: [PATCH 26/49] feat: submission endpoint geimplementeerd (ongetest) --- backend/src/controllers/submissions.ts | 25 +++++++++++++++++++++ backend/src/interfaces/submission.ts | 30 ++++++++++++++++++++++++++ backend/src/routes/learning-objects.ts | 4 ++++ backend/src/routes/submissions.ts | 14 ++++-------- backend/src/services/submissions.ts | 22 +++++++++++++++++++ 5 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 backend/src/controllers/submissions.ts create mode 100644 backend/src/interfaces/submission.ts create mode 100644 backend/src/services/submissions.ts diff --git a/backend/src/controllers/submissions.ts b/backend/src/controllers/submissions.ts new file mode 100644 index 00000000..24449ae8 --- /dev/null +++ b/backend/src/controllers/submissions.ts @@ -0,0 +1,25 @@ +import { Request, Response } from "express"; +import { getSubmission } from "../services/submissions"; +import { Language } from "../entities/content/language"; + +interface SubmissionParams { + lohruid: string, + submissionNumber: number; +} + +export async function getSubmissionHandler( + req: Request, + res: Response, +): Promise { + const lohruid = req.params.lohruid; + const submissionNumber = req.params.submissionNumber; + + const submission = getSubmission(lohruid, Language.Dutch, '1', submissionNumber); + + if (!submission) { + res.status(404).json({ error: 'Submission not found' }); + return; + } + + res.json(submission); +} \ No newline at end of file diff --git a/backend/src/interfaces/submission.ts b/backend/src/interfaces/submission.ts new file mode 100644 index 00000000..daf00a64 --- /dev/null +++ b/backend/src/interfaces/submission.ts @@ -0,0 +1,30 @@ +import { Submission } from "../entities/assignments/submission.entity"; +import { Language } from "../entities/content/language"; +import { GroupDTO, mapToGroupDTO } from "./group"; +import { mapToStudentDTO, StudentDTO } from "./student"; + +export interface SubmissionDTO { + learningObjectHruid: string, + learningObjectLanguage: Language, + learningObjectVersion: string, + + submissionNumber: number, + submitter: StudentDTO | string, + time: Date, + group?: GroupDTO | string, + content: string, +} + +export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { + return { + learningObjectHruid: submission.learningObjectHruid, + learningObjectLanguage: submission.learningObjectLanguage, + learningObjectVersion: submission.learningObjectVersion, + + submissionNumber: submission.submissionNumber, + submitter: mapToStudentDTO(submission.submitter), + time: submission.submissionTime, + group: submission.onBehalfOf ? mapToGroupDTO(submission.onBehalfOf) : undefined, + content: submission.content, + } +} \ No newline at end of file diff --git a/backend/src/routes/learning-objects.ts b/backend/src/routes/learning-objects.ts index 3717095a..77094955 100644 --- a/backend/src/routes/learning-objects.ts +++ b/backend/src/routes/learning-objects.ts @@ -4,6 +4,8 @@ import { getLearningObject, } from '../controllers/learning-objects.js'; +import submissionRoutes from './submissions.js'; + const router = express.Router(); // DWENGO learning objects @@ -24,4 +26,6 @@ router.get('/', getAllLearningObjects); // Example: http://localhost:3000/learningObject/un_ai7 router.get('/:hruid', getLearningObject); +router.use('/:hruid/submissions', submissionRoutes); + export default router; diff --git a/backend/src/routes/submissions.ts b/backend/src/routes/submissions.ts index cb4d3e85..b4e34c74 100644 --- a/backend/src/routes/submissions.ts +++ b/backend/src/routes/submissions.ts @@ -1,6 +1,9 @@ import express from 'express'; +import { getSubmissionHandler } from '../controllers/submissions'; const router = express.Router(); + + // Root endpoint used to search objects router.get('/', (req, res) => { res.json({ @@ -9,15 +12,6 @@ router.get('/', (req, res) => { }); // Information about an submission with id 'id' -router.get('/:id', (req, res) => { - res.json({ - id: req.params.id, - student: '0', - group: '0', - time: new Date(2025, 1, 1), - content: 'Wortel 2 is rationeel', - learningObject: '0', - }); -}); +router.get('/:id', getSubmissionHandler); export default router; diff --git a/backend/src/services/submissions.ts b/backend/src/services/submissions.ts new file mode 100644 index 00000000..2c2e1aad --- /dev/null +++ b/backend/src/services/submissions.ts @@ -0,0 +1,22 @@ +import { getSubmissionRepository } from "../data/repositories"; +import { Language } from "../entities/content/language"; +import { LearningObjectIdentifier } from "../entities/content/learning-object-identifier"; +import { mapToSubmissionDTO, SubmissionDTO } from "../interfaces/submission"; + +export async function getSubmission( + learningObjectHruid: string, + language: Language, + version: string, + submissionNumber: number, +): Promise { + const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); + + const submissionRepository = getSubmissionRepository(); + const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(loId, submissionNumber); + + if (!submission) { + return null; + } + + return mapToSubmissionDTO(submission); +} \ No newline at end of file From fd693dc55ff00fc18425376b1492429a0e78b36f Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Wed, 12 Mar 2025 15:23:33 +0100 Subject: [PATCH 27/49] feat: submissions van een assignment geimplementeerd --- backend/src/controllers/submissions.ts | 14 +++++++-- .../data/assignments/submission-repository.ts | 8 +++++ backend/src/entities/content/language.ts | 7 +++++ backend/src/routes/submissions.ts | 2 +- backend/src/services/assignments.ts | 31 +++++++++++++++++++ 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/submissions.ts b/backend/src/controllers/submissions.ts index 24449ae8..c4911637 100644 --- a/backend/src/controllers/submissions.ts +++ b/backend/src/controllers/submissions.ts @@ -1,6 +1,6 @@ import { Request, Response } from "express"; import { getSubmission } from "../services/submissions"; -import { Language } from "../entities/content/language"; +import { Language, languageMap } from "../entities/content/language"; interface SubmissionParams { lohruid: string, @@ -12,9 +12,17 @@ export async function getSubmissionHandler( res: Response, ): Promise { const lohruid = req.params.lohruid; - const submissionNumber = req.params.submissionNumber; + const submissionNumber = +req.params.submissionNumber; - const submission = getSubmission(lohruid, Language.Dutch, '1', submissionNumber); + if (isNaN(submissionNumber)) { + res.status(404).json({ error: 'Submission number is not a number' }); + return; + } + + let lang = languageMap[req.query.language as string] || Language.Dutch; + let version = req.query.version as string || '1'; + + const submission = getSubmission(lohruid, lang, version, submissionNumber); if (!submission) { res.status(404).json({ error: 'Submission not found' }); diff --git a/backend/src/data/assignments/submission-repository.ts b/backend/src/data/assignments/submission-repository.ts index 5332d050..a4d34826 100644 --- a/backend/src/data/assignments/submission-repository.ts +++ b/backend/src/data/assignments/submission-repository.ts @@ -47,6 +47,14 @@ export class SubmissionRepository extends DwengoEntityRepository { ); } + public findAllSubmissionsForGroup( + group: Group, + ): Promise { + return this.find( + { onBehalfOf: group }, + ); + } + public deleteSubmissionByLearningObjectAndSubmissionNumber( loId: LearningObjectIdentifier, submissionNumber: number diff --git a/backend/src/entities/content/language.ts b/backend/src/entities/content/language.ts index b5d18c80..d62a2f22 100644 --- a/backend/src/entities/content/language.ts +++ b/backend/src/entities/content/language.ts @@ -4,3 +4,10 @@ export enum Language { English = 'en', Germany = 'de', } + +export const languageMap: Record = { + nl: Language.Dutch, + fr: Language.French, + en: Language.English, + de: Language.Germany, +}; \ No newline at end of file diff --git a/backend/src/routes/submissions.ts b/backend/src/routes/submissions.ts index b4e34c74..744b9e16 100644 --- a/backend/src/routes/submissions.ts +++ b/backend/src/routes/submissions.ts @@ -1,6 +1,6 @@ import express from 'express'; import { getSubmissionHandler } from '../controllers/submissions'; -const router = express.Router(); +const router = express.Router({ mergeParams: true }); diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index 1ecfb4d4..1f50a1c9 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -1,12 +1,15 @@ import { getAssignmentRepository, getClassRepository, + getGroupRepository, + getSubmissionRepository, } from '../data/repositories.js'; import { AssignmentDTO, mapToAssignmentDTO, mapToAssignmentDTOId, } from '../interfaces/assignment.js'; +import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; export async function getAllAssignments( classid: string, @@ -50,3 +53,31 @@ export async function getAssignment( return mapToAssignmentDTO(assignment); } + +export async function getAssignmentsSubmissions( + classid: string, + assignmentNumber: number, +): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classid); + + if (!cls) { + return []; + } + + const assignmentRepository = getAssignmentRepository(); + const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); + + if (!assignment) { + return []; + } + + const groupRepository = getGroupRepository(); + const groups = await groupRepository.findAllGroupsForAssignment(assignment); + + const submissionRepository = getSubmissionRepository(); + const submissions = + (await Promise.all(groups.map(group => submissionRepository.findAllSubmissionsForGroup(group)))).flat(); + + return submissions.map(mapToSubmissionDTO); +} \ No newline at end of file From 788ca54742af42f53e837820bb0d5252c26d2d07 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Wed, 12 Mar 2025 15:26:50 +0100 Subject: [PATCH 28/49] feat: verbinding tussen service laag en api endpoint van submissions van een assignment --- backend/src/controllers/assignments.ts | 21 ++++++++++++++++++++- backend/src/routes/assignments.ts | 7 ++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index b1be1302..58897410 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import { getAllAssignments, getAssignment } from '../services/assignments.js'; +import { getAllAssignments, getAssignment, getAssignmentsSubmissions } from '../services/assignments.js'; // Typescript is annoy with with parameter forwarding from class.ts interface AssignmentParams { @@ -42,3 +42,22 @@ export async function getAssignmentHandler( res.json(assignment); } + +export async function getAssignmentsSubmissionsHandler( + req: Request, + res: Response, +): Promise { + const classid = req.params.classid; + const assignmentNumber = +req.params.id; + + if (isNaN(assignmentNumber)) { + res.status(400).json({ error: 'Assignment id must be a number' }); + return; + } + + const submissions = await getAssignmentsSubmissions(classid, assignmentNumber); + + res.json({ + submissions: submissions, + }); +} diff --git a/backend/src/routes/assignments.ts b/backend/src/routes/assignments.ts index 85f3bc82..bbc29194 100644 --- a/backend/src/routes/assignments.ts +++ b/backend/src/routes/assignments.ts @@ -2,6 +2,7 @@ import express from 'express'; import { getAllAssignmentsHandler, getAssignmentHandler, + getAssignmentsSubmissionsHandler, } from '../controllers/assignments.js'; import groupRouter from './groups.js'; @@ -13,11 +14,7 @@ router.get('/', getAllAssignmentsHandler); // Information about an assignment with id 'id' router.get('/:id', getAssignmentHandler); -router.get('/:id/submissions', (req, res) => { - res.json({ - submissions: ['0'], - }); -}); +router.get('/:id/submissions', getAssignmentsSubmissionsHandler); router.get('/:id/questions', (req, res) => { res.json({ From d8b97f3aea345ed7674fd0960956e20209d9843a Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Wed, 12 Mar 2025 15:32:26 +0100 Subject: [PATCH 29/49] feat: verbinding student submissions --- backend/src/controllers/students.ts | 14 ++++++++++++++ .../data/assignments/submission-repository.ts | 8 ++++++++ backend/src/routes/students.ts | 7 ++----- backend/src/services/students.ts | 18 ++++++++++++++++++ 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index a104979a..9a052a86 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -3,6 +3,7 @@ import { getStudentAssignments, getStudentClasses, getStudentGroups, + getStudentSubmissions, StudentService, } from '../services/students.js'; import { ClassDTO } from '../interfaces/class.js'; @@ -101,3 +102,16 @@ export async function getStudentGroupsHandler( groups: groups, }); } + +export async function getStudentSubmissionsHandler( + req: Request, + res: Response, +): Promise { + const username = req.params.id; + + const submissions = await getStudentSubmissions(username); + + res.json({ + submissions: submissions, + }); +} diff --git a/backend/src/data/assignments/submission-repository.ts b/backend/src/data/assignments/submission-repository.ts index a4d34826..6ec1217f 100644 --- a/backend/src/data/assignments/submission-repository.ts +++ b/backend/src/data/assignments/submission-repository.ts @@ -55,6 +55,14 @@ export class SubmissionRepository extends DwengoEntityRepository { ); } + public findAllSubmissionsForStudent( + student: Student, + ): Promise { + return this.find( + { submitter: student }, + ); + } + public deleteSubmissionByLearningObjectAndSubmissionNumber( loId: LearningObjectIdentifier, submissionNumber: number diff --git a/backend/src/routes/students.ts b/backend/src/routes/students.ts index c18b3e1c..0c8babce 100644 --- a/backend/src/routes/students.ts +++ b/backend/src/routes/students.ts @@ -7,6 +7,7 @@ import { getStudentClassesHandler, getStudentGroupsHandler, getStudentHandler, + getStudentSubmissionsHandler, } from '../controllers/students.js'; import { getStudentGroups } from '../services/students.js'; const router = express.Router(); @@ -25,11 +26,7 @@ router.get('/:username', getStudentHandler); router.get('/:id/classes', getStudentClassesHandler); // The list of submissions a student has made -router.get('/:id/submissions', (req, res) => { - res.json({ - submissions: ['0'], - }); -}); +router.get('/:id/submissions', getStudentSubmissionsHandler); // The list of assignments a student has router.get('/:id/assignments', getStudentAssignmentsHandler); diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index fc0a8e1d..9524f281 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -2,12 +2,14 @@ import { getClassRepository, getGroupRepository, getStudentRepository, + getSubmissionRepository, } from '../data/repositories.js'; import { Class } from '../entities/classes/class.entity.js'; import { Student } from '../entities/users/student.entity.js'; import { AssignmentDTO } from '../interfaces/assignment.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; +import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; import { getAllAssignments } from './assignments.js'; import { UserService } from './users.js'; @@ -74,3 +76,19 @@ export async function getStudentGroups(username: string, full: boolean): Promise return groups.map(mapToGroupDTOId); } + +export async function getStudentSubmissions( + username: string +): Promise { + const studentRepository = getStudentRepository(); + const student = await studentRepository.findByUsername(username); + + if (!student) { + return []; + } + + const submissionRepository = getSubmissionRepository(); + const submissions = await submissionRepository.findAllSubmissionsForStudent(student); + + return submissions.map(mapToSubmissionDTO); +} \ No newline at end of file From e8975878aa596654641527adb47156fb45f434ef Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Wed, 12 Mar 2025 15:41:56 +0100 Subject: [PATCH 30/49] feat: verbinding tussen groepen en hun submissions --- backend/src/controllers/groups.ts | 30 ++++++++++++++++++++++- backend/src/routes/groups.ts | 4 +++- backend/src/services/groups.ts | 40 +++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index e484c409..8b26b810 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import { getAllGroups, getGroup } from '../services/groups.js'; +import { getAllGroups, getGroup, getGroupSubmissions } from '../services/groups.js'; // Typescript is annoywith with parameter forwarding from class.ts interface GroupParams { @@ -53,3 +53,31 @@ export async function getAllGroupsHandler( groups: groups, }); } + +export async function getGroupSubmissionsHandler( + req: Request, + res: Response, +): Promise { + const classId = req.params.classid; + // const full = req.query.full === 'true'; + + const assignmentId = +req.params.assignmentid; + + if (isNaN(assignmentId)) { + res.status(400).json({ error: 'Assignment id must be a number' }); + return; + } + + const groupId = +req.params.groupid!; // Can't be undefined + + if (isNaN(groupId)) { + res.status(400).json({ error: 'Group id must be a number' }); + return; + } + + const submissions = await getGroupSubmissions(classId, assignmentId, groupId); + + res.json({ + submissions: submissions, + }); +} \ No newline at end of file diff --git a/backend/src/routes/groups.ts b/backend/src/routes/groups.ts index d604c088..d17a330e 100644 --- a/backend/src/routes/groups.ts +++ b/backend/src/routes/groups.ts @@ -1,5 +1,5 @@ import express from 'express'; -import { getAllGroupsHandler, getGroupHandler } from '../controllers/groups.js'; +import { getAllGroupsHandler, getGroupHandler, getGroupSubmissionsHandler } from '../controllers/groups.js'; const router = express.Router({ mergeParams: true }); @@ -9,6 +9,8 @@ router.get('/', getAllGroupsHandler); // Information about a group (members, ... [TODO DOC]) router.get('/:groupid', getGroupHandler); +router.get('/:groupid', getGroupSubmissionsHandler); + // The list of questions a group has made router.get('/:id/question', (req, res) => { res.json({ diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index 467f90a3..a2af8e4a 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -2,12 +2,14 @@ import { getAssignmentRepository, getClassRepository, getGroupRepository, + getSubmissionRepository, } from '../data/repositories.js'; import { GroupDTO, mapToGroupDTO, mapToGroupDTOId, } from '../interfaces/group.js'; +import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; export async function getGroup( classId: string, @@ -82,3 +84,41 @@ export async function getAllGroups( return groups.map(mapToGroupDTOId); } + +export async function getGroupSubmissions( + classId: string, + assignmentNumber: number, + groupNumber: number, +): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classId); + + if (!cls) { + return []; + } + + const assignmentRepository = getAssignmentRepository(); + const assignment = await assignmentRepository.findByClassAndId( + cls, + assignmentNumber + ); + + if (!assignment) { + return []; + } + + const groupRepository = getGroupRepository(); + const group = await groupRepository.findByAssignmentAndGroupNumber( + assignment, + groupNumber + ); + + if (!group) { + return []; + } + + const submissionRepository = getSubmissionRepository(); + const submissions = await submissionRepository.findAllSubmissionsForGroup(group); + + return submissions.map(mapToSubmissionDTO); +} From 3e2c73320b0f7353734fb5371d3ce8ae95a5f752 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Thu, 13 Mar 2025 13:54:45 +0100 Subject: [PATCH 31/49] fix: voeg .js toe submission --- backend/src/controllers/submissions.ts | 6 +++--- backend/src/interfaces/submission.ts | 10 +++++----- backend/src/routes/submissions.ts | 2 +- backend/src/services/submissions.ts | 14 +++++++------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/backend/src/controllers/submissions.ts b/backend/src/controllers/submissions.ts index c4911637..572dae43 100644 --- a/backend/src/controllers/submissions.ts +++ b/backend/src/controllers/submissions.ts @@ -1,6 +1,6 @@ import { Request, Response } from "express"; -import { getSubmission } from "../services/submissions"; -import { Language, languageMap } from "../entities/content/language"; +import { getSubmission } from "../services/submissions.js"; +import { Language, languageMap } from "../entities/content/language.js"; interface SubmissionParams { lohruid: string, @@ -30,4 +30,4 @@ export async function getSubmissionHandler( } res.json(submission); -} \ No newline at end of file +} diff --git a/backend/src/interfaces/submission.ts b/backend/src/interfaces/submission.ts index daf00a64..e0fddf07 100644 --- a/backend/src/interfaces/submission.ts +++ b/backend/src/interfaces/submission.ts @@ -1,7 +1,7 @@ -import { Submission } from "../entities/assignments/submission.entity"; -import { Language } from "../entities/content/language"; -import { GroupDTO, mapToGroupDTO } from "./group"; -import { mapToStudentDTO, StudentDTO } from "./student"; +import { Submission } from "../entities/assignments/submission.entity.js"; +import { Language } from "../entities/content/language.js"; +import { GroupDTO, mapToGroupDTO } from "./group.js"; +import { mapToStudentDTO, StudentDTO } from "./student.js"; export interface SubmissionDTO { learningObjectHruid: string, @@ -27,4 +27,4 @@ export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { group: submission.onBehalfOf ? mapToGroupDTO(submission.onBehalfOf) : undefined, content: submission.content, } -} \ No newline at end of file +} diff --git a/backend/src/routes/submissions.ts b/backend/src/routes/submissions.ts index 744b9e16..1be419d4 100644 --- a/backend/src/routes/submissions.ts +++ b/backend/src/routes/submissions.ts @@ -1,5 +1,5 @@ import express from 'express'; -import { getSubmissionHandler } from '../controllers/submissions'; +import { getSubmissionHandler } from '../controllers/submissions.js'; const router = express.Router({ mergeParams: true }); diff --git a/backend/src/services/submissions.ts b/backend/src/services/submissions.ts index 2c2e1aad..c805c717 100644 --- a/backend/src/services/submissions.ts +++ b/backend/src/services/submissions.ts @@ -1,15 +1,15 @@ -import { getSubmissionRepository } from "../data/repositories"; -import { Language } from "../entities/content/language"; -import { LearningObjectIdentifier } from "../entities/content/learning-object-identifier"; -import { mapToSubmissionDTO, SubmissionDTO } from "../interfaces/submission"; +import { getSubmissionRepository } from "../data/repositories.js"; +import { Language } from "../entities/content/language.js"; +import { LearningObjectIdentifier } from "../entities/content/learning-object-identifier.js"; +import { mapToSubmissionDTO, SubmissionDTO } from "../interfaces/submission.js"; export async function getSubmission( learningObjectHruid: string, language: Language, version: string, - submissionNumber: number, + submissionNumber: number, ): Promise { - const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); + const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); const submissionRepository = getSubmissionRepository(); const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(loId, submissionNumber); @@ -19,4 +19,4 @@ export async function getSubmission( } return mapToSubmissionDTO(submission); -} \ No newline at end of file +} From a1aaf342d7554e4bb821958df480ee51c031a634 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Thu, 13 Mar 2025 14:39:12 +0100 Subject: [PATCH 32/49] feat: POST method voor assignment geimplementeerd --- backend/src/controllers/assignments.ts | 32 ++++++++++++++++++- .../entities/assignments/assignment.entity.ts | 4 +-- backend/src/interfaces/assignment.ts | 20 ++++++++++-- backend/src/routes/assignments.ts | 3 ++ backend/src/services/assignments.ts | 27 ++++++++++++++++ 5 files changed, 81 insertions(+), 5 deletions(-) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 58897410..dcaa07a2 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,5 +1,7 @@ import { Request, Response } from 'express'; -import { getAllAssignments, getAssignment, getAssignmentsSubmissions } from '../services/assignments.js'; +import { createAssignment, getAllAssignments, getAssignment, getAssignmentsSubmissions } from '../services/assignments.js'; +import { AssignmentDTO, mapToAssignment, mapToAssignmentDTO } from '../interfaces/assignment.js'; +import { getAssignmentRepository, getClassRepository } from '../data/repositories.js'; // Typescript is annoy with with parameter forwarding from class.ts interface AssignmentParams { @@ -21,6 +23,34 @@ export async function getAllAssignmentsHandler( }); } +export async function createAssignmentHandler( + req: Request, + res: Response, +): Promise { + const classid = req.params.classid; + const assignmentData = req.body as AssignmentDTO; + + if (!assignmentData.description + || !assignmentData.language + || !assignmentData.learningPath + || !assignmentData.title + ) { + res.status(400).json({ + error: 'Missing one or more required fields: title, description, learningPath, title', + }); + return; + } + + const assignment = createAssignment(classid, assignmentData); + + if (!assignment) { + res.status(500).json({ error: "Could not create assignment "}); + return; + } + + res.status(201).json({ assignment: assignment }); +} + export async function getAssignmentHandler( req: Request, res: Response diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index f6e3c3eb..ecb02b90 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -25,8 +25,8 @@ export class Assignment { }) within!: Class; - @PrimaryKey({ type: 'number' }) - id!: number; + @PrimaryKey({ type: 'number', autoincrement: true }) + id?: number; @Property({ type: 'string' }) title!: string; diff --git a/backend/src/interfaces/assignment.ts b/backend/src/interfaces/assignment.ts index ad6d8330..de7ce25f 100644 --- a/backend/src/interfaces/assignment.ts +++ b/backend/src/interfaces/assignment.ts @@ -1,4 +1,7 @@ +import { FALLBACK_LANG } from '../config.js'; import { Assignment } from '../entities/assignments/assignment.entity.js'; +import { Class } from '../entities/classes/class.entity.js'; +import { languageMap } from '../entities/content/language.js'; import { GroupDTO, mapToGroupDTO } from './group.js'; export interface AssignmentDTO { @@ -13,7 +16,7 @@ export interface AssignmentDTO { export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { return { - id: assignment.id, + id: assignment.id!, class: assignment.within.classId, title: assignment.title, description: assignment.description, @@ -25,7 +28,7 @@ export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO { return { - id: assignment.id, + id: assignment.id!, class: assignment.within.classId, title: assignment.title, description: assignment.description, @@ -34,3 +37,16 @@ export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO { // Groups: assignment.groups.map(mapToGroupDTO), }; } + +export function mapToAssignment(assignmentData: AssignmentDTO, cls: Class): Assignment { + const assignment = new Assignment(); + assignment.title = assignmentData.title; + assignment.description = assignmentData.description; + assignment.learningPathHruid = assignmentData.learningPath; + assignment.learningPathLanguage = languageMap[assignmentData.language] || FALLBACK_LANG; + assignment.within = cls; + + console.log(assignment); + + return assignment; +} diff --git a/backend/src/routes/assignments.ts b/backend/src/routes/assignments.ts index bbc29194..a733d093 100644 --- a/backend/src/routes/assignments.ts +++ b/backend/src/routes/assignments.ts @@ -1,5 +1,6 @@ import express from 'express'; import { + createAssignmentHandler, getAllAssignmentsHandler, getAssignmentHandler, getAssignmentsSubmissionsHandler, @@ -11,6 +12,8 @@ const router = express.Router({ mergeParams: true }); // Root endpoint used to search objects router.get('/', getAllAssignmentsHandler); +router.post('/', createAssignmentHandler); + // Information about an assignment with id 'id' router.get('/:id', getAssignmentHandler); diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index 1f50a1c9..e67c2c0c 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -4,8 +4,10 @@ import { getGroupRepository, getSubmissionRepository, } from '../data/repositories.js'; +import { Assignment } from '../entities/assignments/assignment.entity.js'; import { AssignmentDTO, + mapToAssignment, mapToAssignmentDTO, mapToAssignmentDTOId, } from '../interfaces/assignment.js'; @@ -33,6 +35,31 @@ export async function getAllAssignments( return assignments.map(mapToAssignmentDTOId); } +export async function createAssignment( + classid: string, + assignmentData: AssignmentDTO, +): Promise { + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classid); + + if (!cls) { + return null; + } + + const assignment = mapToAssignment(assignmentData, cls); + const assignmentRepository = getAssignmentRepository(); + + try { + const newAssignment = assignmentRepository.create(assignment); + await assignmentRepository.save(newAssignment); + + return newAssignment; + } catch(e) { + return null; + } + +} + export async function getAssignment( classid: string, id: number From 3dd1edc95de924b6a1e7b3355f4e9d07af4f020c Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Thu, 13 Mar 2025 15:02:11 +0100 Subject: [PATCH 33/49] feat: question route als subroute van learning objects --- backend/src/controllers/questions.ts | 118 +++++++++++++++++++++++++ backend/src/interfaces/answer.ts | 38 ++++++++ backend/src/interfaces/question.ts | 52 ++++++----- backend/src/routes/learning-objects.ts | 4 + backend/src/routes/questions.ts | 44 ++++----- backend/src/services/questions.ts | 103 +++++++++++++++++++++ 6 files changed, 310 insertions(+), 49 deletions(-) create mode 100644 backend/src/controllers/questions.ts create mode 100644 backend/src/interfaces/answer.ts create mode 100644 backend/src/services/questions.ts diff --git a/backend/src/controllers/questions.ts b/backend/src/controllers/questions.ts new file mode 100644 index 00000000..850dcdf7 --- /dev/null +++ b/backend/src/controllers/questions.ts @@ -0,0 +1,118 @@ +import {Request, Response} from "express"; +import { + createQuestion, + deleteQuestion, + getAllQuestions, + getAnswersByQuestion, + getQuestion +} from "../services/questions.js"; +import {QuestionDTO, QuestionId} from "../interfaces/question.js"; +import {FALLBACK_LANG, FALLBACK_SEQ_NUM} from "../config.js"; +import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; +import {Language} from "../entities/content/language.js"; + +function getObjectId(req: Request, res: Response): LearningObjectIdentifier | null { + const { hruid, version} = req.params + const lang = req.query.lang + + if (!hruid || !version ) { + res.status(400).json({ error: "Missing required parameters." }); + return null; + } + + return { + hruid, + language: lang as Language || FALLBACK_LANG, + version + } +} + +function getQuestionId(req: Request, res: Response): QuestionId | null { + const seq = req.params.seq + const learningObjectIdentifier = getObjectId(req,res); + + if (!learningObjectIdentifier) + return null + + return { + learningObjectIdentifier, + sequenceNumber: seq ? Number(seq) : FALLBACK_SEQ_NUM + } +} + +export async function getAllQuestionsHandler( + req: Request, + res: Response +): Promise { + const objectId = getObjectId(req, res); + const full = req.query.full === 'true'; + + if (!objectId) + return + + const questions = await getAllQuestions(objectId, full); + + if (!questions) + res.status(404).json({ error: `Questions not found.` }); + else + res.json(questions); +} + +export async function getQuestionHandler(req: Request, res: Response): Promise { + const questionId = getQuestionId(req, res); + + if (!questionId) + return + + const question = await getQuestion(questionId); + + if (!question) + res.status(404).json({ error: `Question not found.` }); + else + res.json(question) +} + +export async function getQuestionAnswersHandler(req: Request, res: Response): Promise { + const questionId = getQuestionId(req, res); + const full = req.query.full === 'true'; + + if (!questionId) + return + + const answers = getAnswersByQuestion(questionId, full); + + if (!answers) + res.status(404).json({ error: `Questions not found.` }); + else + res.json(answers) +} + +export async function createQuestionHandler(req: Request, res: Response): Promise { + const questionDTO = req.body as QuestionDTO; + + if (!questionDTO.learningObjectIdentifier || !questionDTO.author || !questionDTO.content) { + res.status(400).json({error: 'Missing required fields: identifier and content'}); + return; + } + + const question = await createQuestion(questionDTO); + + if (!question) + res.status(400).json({error: 'Could not add question'}); + else + res.json(question) +} + +export async function deleteQuestionHandler(req: Request, res: Response): Promise { + const questionId = getQuestionId(res, req) + + const question = await deleteQuestion(questionId); + + if (!question) + res.status(400).json({error: 'Could not find nor delete question'}); + else + res.json(question) +} + + + diff --git a/backend/src/interfaces/answer.ts b/backend/src/interfaces/answer.ts new file mode 100644 index 00000000..1b363c0d --- /dev/null +++ b/backend/src/interfaces/answer.ts @@ -0,0 +1,38 @@ +import {mapToUserDTO, UserDTO} from "./user.js"; +import {mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId} from "./question.js"; +import {Answer} from "../entities/questions/answer.entity.js"; + +export interface AnswerDTO { + author: UserDTO; + toQuestion: QuestionDTO; + sequenceNumber: number; + timestamp: string; + content: string; +} + +/** + * Convert a Question entity to a DTO format. + */ +export function mapToAnswerDTO(answer: Answer): AnswerDTO { + return { + author: mapToUserDTO(answer.author), + toQuestion: mapToQuestionDTO(answer.toQuestion), + sequenceNumber: answer.sequenceNumber, + timestamp: answer.timestamp.toISOString(), + content: answer.content, + }; +} + +export interface AnswerId { + author: string; + toQuestion: QuestionId; + sequenceNumber: number; +} + +export function mapToAnswerId(answer: AnswerDTO): AnswerId { + return { + author: answer.author.username, + toQuestion: mapToQuestionId(answer.toQuestion), + sequenceNumber: answer.sequenceNumber + } +} diff --git a/backend/src/interfaces/question.ts b/backend/src/interfaces/question.ts index 90de4999..33dced69 100644 --- a/backend/src/interfaces/question.ts +++ b/backend/src/interfaces/question.ts @@ -1,48 +1,56 @@ import { Question } from '../entities/questions/question.entity.js'; +import {mapToUserDTO, UserDTO} from "./user.js"; +import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; +import {Teacher} from "../entities/users/teacher.entity"; export interface QuestionDTO { - learningObjectHruid: string; - learningObjectLanguage: string; - learningObjectVersion: string; - sequenceNumber: number; - authorUsername: string; - timestamp: string; + learningObjectIdentifier: LearningObjectIdentifier; + sequenceNumber?: number; + author: UserDTO; + timestamp?: string; content: string; - endpoints?: { - classes: string; - questions: string; - invitations: string; - groups: string; - }; } /** * Convert a Question entity to a DTO format. */ export function mapToQuestionDTO(question: Question): QuestionDTO { + const learningObjectIdentifier = { + hruid: question.learningObjectHruid, + language: question.learningObjectLanguage, + version: question.learningObjectVersion + } + return { - learningObjectHruid: question.learningObjectHruid, - learningObjectLanguage: question.learningObjectLanguage, - learningObjectVersion: question.learningObjectVersion, + learningObjectIdentifier, sequenceNumber: question.sequenceNumber, - authorUsername: question.author.username, + author: question.author, timestamp: question.timestamp.toISOString(), content: question.content, }; } export interface QuestionId { - learningObjectHruid: string; - learningObjectLanguage: string; - learningObjectVersion: string; + learningObjectIdentifier: LearningObjectIdentifier; sequenceNumber: number; } export function mapToQuestionId(question: QuestionDTO): QuestionId { return { - learningObjectHruid: question.learningObjectHruid, - learningObjectLanguage: question.learningObjectLanguage, - learningObjectVersion: question.learningObjectVersion, + learningObjectIdentifier: question.learningObjectIdentifier, sequenceNumber: question.sequenceNumber, }; } + +export function mapToQuestion(questionDTO: QuestionDTO): Question { + const question = new Question(); + question.author = mapToUserDTO(questionDTO.author); + question.learningObjectHruid = questionDTO.learningObjectIdentifier.hruid; + question.learningObjectLanguage = questionDTO.learningObjectIdentifier.language; + question.learningObjectVersion = questionDTO.learningObjectIdentifier.version; + question.content = questionDTO.content; + question.sequenceNumber = questionDTO.sequenceNumber; + question.timestamp = questionDTO.timestamp; + + return question; +} diff --git a/backend/src/routes/learning-objects.ts b/backend/src/routes/learning-objects.ts index 77094955..6b708d4b 100644 --- a/backend/src/routes/learning-objects.ts +++ b/backend/src/routes/learning-objects.ts @@ -5,6 +5,8 @@ import { } from '../controllers/learning-objects.js'; import submissionRoutes from './submissions.js'; +import questionRoutes from './questions.js'; + const router = express.Router(); @@ -28,4 +30,6 @@ router.get('/:hruid', getLearningObject); router.use('/:hruid/submissions', submissionRoutes); +router.use('/:hruid/:version/questions', questionRoutes) + export default router; diff --git a/backend/src/routes/questions.ts b/backend/src/routes/questions.ts index f683d998..d635a85e 100644 --- a/backend/src/routes/questions.ts +++ b/backend/src/routes/questions.ts @@ -1,34 +1,24 @@ import express from 'express'; -const router = express.Router(); +import { + createQuestionHandler, deleteQuestionHandler, + getAllQuestionsHandler, + getQuestionAnswersHandler, + getQuestionHandler +} from "../controllers/questions.js"; +const router = express.Router({ mergeParams: true }); + +// query language // Root endpoint used to search objects -router.get('/', (req, res) => { - res.json({ - questions: ['0', '1'], - }); -}); +router.get('/', getAllQuestionsHandler); -// Information about an question with id 'id' -router.get('/:id', (req, res) => { - res.json({ - id: req.params.id, - student: '0', - group: '0', - time: new Date(2025, 1, 1), - content: - 'Zijn alle gehele getallen groter dan 2 gelijk aan de som van 2 priemgetallen????', - learningObject: '0', - links: { - self: `${req.baseUrl}/${req.params.id}`, - answers: `${req.baseUrl}/${req.params.id}/answers`, - }, - }); -}); +router.post('/', createQuestionHandler); -router.get('/:id/answers', (req, res) => { - res.json({ - answers: ['0'], - }); -}); +router.delete('/:seq', deleteQuestionHandler); + +// Information about a question with id +router.get('/:seq', getQuestionHandler); + +router.get('/answers/:seq', getQuestionAnswersHandler); export default router; diff --git a/backend/src/services/questions.ts b/backend/src/services/questions.ts new file mode 100644 index 00000000..e3c64bbb --- /dev/null +++ b/backend/src/services/questions.ts @@ -0,0 +1,103 @@ +import {getAnswerRepository, getQuestionRepository} from "../data/repositories.js"; +import {mapToQuestion, mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId} from "../interfaces/question.js"; +import {Question} from "../entities/questions/question.entity.js"; +import {Answer} from "../entities/questions/answer.entity.js"; +import {mapToAnswerDTO, mapToAnswerId} from "../interfaces/answer.js"; +import {QuestionRepository} from "../data/questions/question-repository.js"; +import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; + +export async function getAllQuestions( + id: LearningObjectIdentifier, full: boolean +): Promise { + const questionRepository: QuestionRepository = getQuestionRepository(); + const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); + + if (!questions) { + return []; + } + + const questionsDTO: QuestionDTO[] = questions.map(mapToQuestionDTO); + + if (full) { + return questionsDTO; + } + + return questionsDTO.map(mapToQuestionId); +} + +async function fetchQuestion(questionId: QuestionId): Promise { + const questionRepository = getQuestionRepository(); + + return await questionRepository.findOne( + { + learningObjectHruid: questionId.learningObjectIdentifier.hruid, + learningObjectLanguage: questionId.learningObjectIdentifier.language, + learningObjectVersion: questionId.learningObjectIdentifier.version, + sequenceNumber: questionId.sequenceNumber + } + ) +} + +export async function getQuestion(questionId: QuestionId): Promise { + const question = await fetchQuestion(questionId); + + if (!question) + return null + + return mapToQuestionDTO(question); +} + +export async function getAnswersByQuestion(questionId: QuestionId, full: boolean) { + const answerRepository = getAnswerRepository(); + const question = await fetchQuestion(questionId); + + if (!question) + return []; + + const answers: Answer[] = await answerRepository.findAllAnswersToQuestion(question); + + if (!answers) + return [] + + const answersDTO = answers.map(mapToAnswerDTO); + + if (full) + return answersDTO + + return answersDTO.map(mapToAnswerId); +} + +export async function createQuestion(questionDTO: QuestionDTO) { + const questionRepository = getQuestionRepository(); + const question = mapToQuestion(questionDTO); + + try { + const newQuestion = questionRepository.create(question) + await questionRepository.save(newQuestion); + } catch (e) { + return null + } + + return newQuestion; +} + +export async function deleteQuestion(questionId: QuestionId) { + const questionRepository = getQuestionRepository(); + + const question = await fetchQuestion(questionId); + + if (!question) + return null + + try { + await questionRepository.removeQuestionByLearningObjectAndSequenceNumber( + questionId.learningObjectIdentifier, questionId.sequenceNumber + ); + } catch (e) { + return null + } + + return question +} + + From 79422ab85429a440f0908603f38d4a7cdae36199 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Thu, 13 Mar 2025 15:11:29 +0100 Subject: [PATCH 34/49] feat: POST method voor class geimplementeerd --- backend/src/controllers/classes.ts | 26 +++++++++++++++ backend/src/entities/classes/class.entity.ts | 2 +- backend/src/interfaces/assignment.ts | 4 +-- backend/src/interfaces/class.ts | 18 ++++++++++- backend/src/interfaces/group.ts | 2 +- backend/src/routes/classes.ts | 3 ++ backend/src/services/class.ts | 34 +++++++++++++++++++- backend/src/services/students.ts | 4 +-- 8 files changed, 85 insertions(+), 8 deletions(-) diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index b8061b5a..5fd4ce9d 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,11 +1,14 @@ import { Request, Response } from 'express'; import { + createClass, getAllClasses, getClass, getClassStudents, getClassStudentsIds, getClassTeacherInvitations, } from '../services/class.js'; +import { ClassDTO, mapToClass } from '../interfaces/class.js'; +import { getClassRepository, getStudentRepository, getTeacherRepository } from '../data/repositories.js'; export async function getAllClassesHandler( req: Request, @@ -19,6 +22,29 @@ export async function getAllClassesHandler( }); } +export async function createClassHandler( + req: Request, + res: Response, +): Promise { + const classData = req.body as ClassDTO; + + if (!classData.displayName) { + res.status(400).json({ + error: 'Missing one or more required fields: displayName', + }); + return; + } + + const cls = await createClass(classData); + + if (!cls) { + res.status(500).json({ error: "Something went wrong while creating class" }); + return + } + + res.status(201).json({ class: cls }); +} + export async function getClassHandler( req: Request, res: Response diff --git a/backend/src/entities/classes/class.entity.ts b/backend/src/entities/classes/class.entity.ts index b40b5baf..b9fd4d0e 100644 --- a/backend/src/entities/classes/class.entity.ts +++ b/backend/src/entities/classes/class.entity.ts @@ -17,7 +17,7 @@ import { ClassRepository } from '../../data/classes/class-repository.js'; }) export class Class { @PrimaryKey() - classId = v4(); + classId? = v4(); @Property({ type: 'string' }) displayName!: string; diff --git a/backend/src/interfaces/assignment.ts b/backend/src/interfaces/assignment.ts index de7ce25f..8f6120b6 100644 --- a/backend/src/interfaces/assignment.ts +++ b/backend/src/interfaces/assignment.ts @@ -17,7 +17,7 @@ export interface AssignmentDTO { export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { return { id: assignment.id!, - class: assignment.within.classId, + class: assignment.within.classId!, title: assignment.title, description: assignment.description, learningPath: assignment.learningPathHruid, @@ -29,7 +29,7 @@ export function mapToAssignmentDTOId(assignment: Assignment): AssignmentDTO { export function mapToAssignmentDTO(assignment: Assignment): AssignmentDTO { return { id: assignment.id!, - class: assignment.within.classId, + class: assignment.within.classId!, title: assignment.title, description: assignment.description, learningPath: assignment.learningPathHruid, diff --git a/backend/src/interfaces/class.ts b/backend/src/interfaces/class.ts index c18ee842..379a8635 100644 --- a/backend/src/interfaces/class.ts +++ b/backend/src/interfaces/class.ts @@ -1,4 +1,7 @@ +import { Collection } from '@mikro-orm/core'; import { Class } from '../entities/classes/class.entity.js'; +import { Student } from '../entities/users/student.entity.js'; +import { Teacher } from '../entities/users/teacher.entity.js'; export interface ClassDTO { id: string; @@ -16,7 +19,7 @@ export interface ClassDTO { export function mapToClassDTO(cls: Class): ClassDTO { return { - id: cls.classId, + id: cls.classId!, displayName: cls.displayName, teachers: cls.teachers.map((teacher) => { return teacher.username; @@ -27,3 +30,16 @@ export function mapToClassDTO(cls: Class): ClassDTO { joinRequests: [], // TODO }; } + +export function mapToClass( + classData: ClassDTO, + students: Collection, + teachers: Collection +): Class { + const cls = new Class(); + cls.displayName = classData.displayName; + cls.students = students; + cls.teachers = teachers; + + return cls; +} diff --git a/backend/src/interfaces/group.ts b/backend/src/interfaces/group.ts index 9c4cecdc..ca7f687a 100644 --- a/backend/src/interfaces/group.ts +++ b/backend/src/interfaces/group.ts @@ -18,7 +18,7 @@ export function mapToGroupDTO(group: Group): GroupDTO { export function mapToGroupDTOId(group: Group): GroupDTO { return { - assignment: group.assignment.id, + assignment: group.assignment.id!, groupNumber: group.groupNumber, members: group.members.map((member) => { return member.username; diff --git a/backend/src/routes/classes.ts b/backend/src/routes/classes.ts index c67b573b..e0972988 100644 --- a/backend/src/routes/classes.ts +++ b/backend/src/routes/classes.ts @@ -1,5 +1,6 @@ import express from 'express'; import { + createClassHandler, getAllClassesHandler, getClassHandler, getClassStudentsHandler, @@ -12,6 +13,8 @@ const router = express.Router(); // Root endpoint used to search objects router.get('/', getAllClassesHandler); +router.post('/', createClassHandler); + // Information about an class with id 'id' router.get('/:id', getClassHandler); diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 45185383..a7f5f7ea 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -1,7 +1,10 @@ import { getClassRepository, + getStudentRepository, getTeacherInvitationRepository, + getTeacherRepository, } from '../data/repositories.js'; +import { Class } from '../entities/classes/class.entity.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { @@ -27,10 +30,39 @@ export async function getAllClasses( return classes.map(mapToClassDTO); } return classes.map((cls) => { - return cls.classId; + return cls.classId!; }); } +export async function createClass(classData: ClassDTO): Promise { + const teacherRepository = getTeacherRepository(); + const teacherUsernames = classData.teachers || []; + const teachers = (await Promise.all(teacherUsernames.map(id => teacherRepository.findByUsername(id)))) + .filter(teacher => teacher != null); + + const studentRepository = getStudentRepository(); + const studentUsernames = classData.students || []; + const students = (await Promise.all(studentUsernames.map(id => studentRepository.findByUsername(id)))) + .filter(student => student != null); + + //const cls = mapToClass(classData, teachers, students); + + const classRepository = getClassRepository(); + + try { + const newClass = classRepository.create({ + displayName: classData.displayName, + teachers: teachers, + students: students, + }); + await classRepository.save(newClass); + + return newClass; + } catch(e) { + return null; + } +} + export async function getClass(classId: string): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 9524f281..602ee4e1 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -34,7 +34,7 @@ export async function getStudentClasses(username: string, full: boolean): Promis return classes.map(mapToClassDTO); } - return classes.map((cls) => cls.classId); + return classes.map((cls) => cls.classId!); } export async function getStudentAssignments(username: string, full: boolean): Promise { @@ -51,7 +51,7 @@ export async function getStudentAssignments(username: string, full: boolean): Pr const assignments = ( await Promise.all( classes.map(async (cls) => { - return await getAllAssignments(cls.classId, full); + return await getAllAssignments(cls.classId!, full); }) ) ).flat(); From e3e1fc3f05d2d817e958471e329d32c6b2559a76 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Thu, 13 Mar 2025 15:30:07 +0100 Subject: [PATCH 35/49] fix: gebruik create question functie --- backend/src/config.ts | 6 +++++- backend/src/controllers/questions.ts | 5 ++++- backend/src/interfaces/question.ts | 19 +++---------------- backend/src/services/questions.ts | 16 +++++++++++----- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/backend/src/config.ts b/backend/src/config.ts index 8fd8ec3f..5c7dd858 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -5,6 +5,10 @@ // Load .env file // Dotenv.config(); +import {Language} from "./entities/content/language.js"; + export const DWENGO_API_BASE = 'https://dwengo.org/backend/api'; -export const FALLBACK_LANG = 'nl'; +export const FALLBACK_LANG: Language = Language.Dutch; + +export const FALLBACK_SEQ_NUM = 1; diff --git a/backend/src/controllers/questions.ts b/backend/src/controllers/questions.ts index 850dcdf7..aa39853a 100644 --- a/backend/src/controllers/questions.ts +++ b/backend/src/controllers/questions.ts @@ -104,7 +104,10 @@ export async function createQuestionHandler(req: Request, res: Response): Promis } export async function deleteQuestionHandler(req: Request, res: Response): Promise { - const questionId = getQuestionId(res, req) + const questionId = getQuestionId(req, res); + + if (!questionId) + return const question = await deleteQuestion(questionId); diff --git a/backend/src/interfaces/question.ts b/backend/src/interfaces/question.ts index 33dced69..23c3edea 100644 --- a/backend/src/interfaces/question.ts +++ b/backend/src/interfaces/question.ts @@ -1,7 +1,6 @@ import { Question } from '../entities/questions/question.entity.js'; -import {mapToUserDTO, UserDTO} from "./user.js"; +import {UserDTO} from "./user.js"; import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; -import {Teacher} from "../entities/users/teacher.entity"; export interface QuestionDTO { learningObjectIdentifier: LearningObjectIdentifier; @@ -23,7 +22,7 @@ export function mapToQuestionDTO(question: Question): QuestionDTO { return { learningObjectIdentifier, - sequenceNumber: question.sequenceNumber, + sequenceNumber: question.sequenceNumber!, author: question.author, timestamp: question.timestamp.toISOString(), content: question.content, @@ -38,19 +37,7 @@ export interface QuestionId { export function mapToQuestionId(question: QuestionDTO): QuestionId { return { learningObjectIdentifier: question.learningObjectIdentifier, - sequenceNumber: question.sequenceNumber, + sequenceNumber: question.sequenceNumber!, }; } -export function mapToQuestion(questionDTO: QuestionDTO): Question { - const question = new Question(); - question.author = mapToUserDTO(questionDTO.author); - question.learningObjectHruid = questionDTO.learningObjectIdentifier.hruid; - question.learningObjectLanguage = questionDTO.learningObjectIdentifier.language; - question.learningObjectVersion = questionDTO.learningObjectIdentifier.version; - question.content = questionDTO.content; - question.sequenceNumber = questionDTO.sequenceNumber; - question.timestamp = questionDTO.timestamp; - - return question; -} diff --git a/backend/src/services/questions.ts b/backend/src/services/questions.ts index e3c64bbb..a2fa01c6 100644 --- a/backend/src/services/questions.ts +++ b/backend/src/services/questions.ts @@ -1,10 +1,12 @@ import {getAnswerRepository, getQuestionRepository} from "../data/repositories.js"; -import {mapToQuestion, mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId} from "../interfaces/question.js"; +import {mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId} from "../interfaces/question.js"; import {Question} from "../entities/questions/question.entity.js"; import {Answer} from "../entities/questions/answer.entity.js"; import {mapToAnswerDTO, mapToAnswerId} from "../interfaces/answer.js"; import {QuestionRepository} from "../data/questions/question-repository.js"; import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; +import {mapToUser} from "../interfaces/user.js"; +import {Student} from "../entities/users/student.entity.js"; export async function getAllQuestions( id: LearningObjectIdentifier, full: boolean @@ -69,16 +71,20 @@ export async function getAnswersByQuestion(questionId: QuestionId, full: boolean export async function createQuestion(questionDTO: QuestionDTO) { const questionRepository = getQuestionRepository(); - const question = mapToQuestion(questionDTO); + + const author = mapToUser(questionDTO.author, new Student()) try { - const newQuestion = questionRepository.create(question) - await questionRepository.save(newQuestion); + await questionRepository.createQuestion({ + loId: questionDTO.learningObjectIdentifier, + author, + content: questionDTO.content } + ); } catch (e) { return null } - return newQuestion; + return questionDTO; } export async function deleteQuestion(questionId: QuestionId) { From 4c76a8217868f26741ba4de5fb790cb4c899f124 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Thu, 13 Mar 2025 15:49:13 +0100 Subject: [PATCH 36/49] feat: (broken) POST method voor groep --- backend/src/controllers/groups.ts | 26 +++++++++- .../src/entities/assignments/group.entity.ts | 4 +- backend/src/interfaces/group.ts | 4 +- backend/src/interfaces/teacher-invitation.ts | 2 +- backend/src/routes/groups.ts | 4 +- backend/src/services/groups.ts | 48 +++++++++++++++++++ 6 files changed, 81 insertions(+), 7 deletions(-) diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 8b26b810..5fd90553 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -1,5 +1,6 @@ import { Request, Response } from 'express'; -import { getAllGroups, getGroup, getGroupSubmissions } from '../services/groups.js'; +import { createGroup, getAllGroups, getGroup, getGroupSubmissions } from '../services/groups.js'; +import { GroupDTO } from '../interfaces/group.js'; // Typescript is annoywith with parameter forwarding from class.ts interface GroupParams { @@ -54,6 +55,29 @@ export async function getAllGroupsHandler( }); } +export async function createGroupHandler( + req: Request, + res: Response, +): Promise { + const classid = req.params.classid; + const assignmentId = +req.params.assignmentid; + + if (isNaN(assignmentId)) { + res.status(400).json({ error: 'Assignment id must be a number' }); + return; + } + + const groupData = req.body as GroupDTO; + const group = createGroup(groupData, classid, assignmentId); + + if (!group) { + res.status(500).json({ error: "Something went wrong while creating group" }); + return + } + + res.status(201).json({ group: group }); +} + export async function getGroupSubmissionsHandler( req: Request, res: Response, diff --git a/backend/src/entities/assignments/group.entity.ts b/backend/src/entities/assignments/group.entity.ts index 9c2ed2cf..0db4f6b0 100644 --- a/backend/src/entities/assignments/group.entity.ts +++ b/backend/src/entities/assignments/group.entity.ts @@ -17,8 +17,8 @@ export class Group { }) assignment!: Assignment; - @PrimaryKey({ type: 'integer' }) - groupNumber!: number; + @PrimaryKey({ type: 'integer', autoincrement: true }) + groupNumber?: number; @ManyToMany({ entity: () => { diff --git a/backend/src/interfaces/group.ts b/backend/src/interfaces/group.ts index ca7f687a..2dd3f2c1 100644 --- a/backend/src/interfaces/group.ts +++ b/backend/src/interfaces/group.ts @@ -11,7 +11,7 @@ export interface GroupDTO { export function mapToGroupDTO(group: Group): GroupDTO { return { assignment: mapToAssignmentDTO(group.assignment), // ERROR: , group.assignment.within), - groupNumber: group.groupNumber, + groupNumber: group.groupNumber!, members: group.members.map(mapToStudentDTO), }; } @@ -19,7 +19,7 @@ export function mapToGroupDTO(group: Group): GroupDTO { export function mapToGroupDTOId(group: Group): GroupDTO { return { assignment: group.assignment.id!, - groupNumber: group.groupNumber, + groupNumber: group.groupNumber!, members: group.members.map((member) => { return member.username; }), diff --git a/backend/src/interfaces/teacher-invitation.ts b/backend/src/interfaces/teacher-invitation.ts index badbbbd7..d29e7476 100644 --- a/backend/src/interfaces/teacher-invitation.ts +++ b/backend/src/interfaces/teacher-invitation.ts @@ -24,6 +24,6 @@ export function mapToTeacherInvitationDTOIds( return { sender: invitation.sender.username, receiver: invitation.receiver.username, - class: invitation.class.classId, + class: invitation.class.classId!, }; } diff --git a/backend/src/routes/groups.ts b/backend/src/routes/groups.ts index d17a330e..b3be0f7a 100644 --- a/backend/src/routes/groups.ts +++ b/backend/src/routes/groups.ts @@ -1,11 +1,13 @@ import express from 'express'; -import { getAllGroupsHandler, getGroupHandler, getGroupSubmissionsHandler } from '../controllers/groups.js'; +import { createGroupHandler, getAllGroupsHandler, getGroupHandler, getGroupSubmissionsHandler } from '../controllers/groups.js'; const router = express.Router({ mergeParams: true }); // Root endpoint used to search objects router.get('/', getAllGroupsHandler); +router.post('/', createGroupHandler); + // Information about a group (members, ... [TODO DOC]) router.get('/:groupid', getGroupHandler); diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index a2af8e4a..65e111fb 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -1,9 +1,12 @@ +import { GroupRepository } from '../data/assignments/group-repository.js'; import { getAssignmentRepository, getClassRepository, getGroupRepository, + getStudentRepository, getSubmissionRepository, } from '../data/repositories.js'; +import { Group } from '../entities/assignments/group.entity.js'; import { GroupDTO, mapToGroupDTO, @@ -51,6 +54,51 @@ export async function getGroup( return mapToGroupDTOId(group); } +export async function createGroup( + groupData: GroupDTO, + classid: string, + assignmentNumber: number, +): Promise { + const studentRepository = getStudentRepository(); + + const memberUsernames = groupData.members as string[] || []; // TODO check if groupdata.members is a list + const members = (await Promise.all([...memberUsernames].map(id => studentRepository.findByUsername(id)))) + .filter(student => student != null); + + console.log(members); + + const classRepository = getClassRepository(); + const cls = await classRepository.findById(classid); + + if (!cls) { + return null; + } + + const assignmentRepository = getAssignmentRepository(); + const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); + + if (!assignment) { + return null; + } + + const groupRepository = getGroupRepository(); + try { + console.log('EEEEE'); + const newGroup = groupRepository.create({ + assignment: assignment, + members: members, + }); + console.log('OOOOOO'); + await groupRepository.save(newGroup); + console.log('AAAAAA'); + + return newGroup; + } catch(e) { + console.log(e); + return null; + } +} + export async function getAllGroups( classId: string, assignmentNumber: number, From 53c85eadb09706eeeb4f1c04e2a31dbf224f5c6d Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Thu, 13 Mar 2025 16:39:59 +0100 Subject: [PATCH 37/49] feat: (BROKEN) kolossale bug in POST group aan het fixen --- backend/src/data/users/student-repository.ts | 15 +++++++++++++-- backend/src/data/users/teacher-repository.ts | 10 +++++++++- .../src/entities/assignments/assignment.entity.ts | 3 ++- backend/src/entities/assignments/group.entity.ts | 10 ++++------ backend/src/entities/users/student.entity.ts | 8 ++++++++ backend/src/services/groups.ts | 3 --- 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/backend/src/data/users/student-repository.ts b/backend/src/data/users/student-repository.ts index 6835e430..d3be9081 100644 --- a/backend/src/data/users/student-repository.ts +++ b/backend/src/data/users/student-repository.ts @@ -1,4 +1,15 @@ import { Student } from '../../entities/users/student.entity.js'; -import { UserRepository } from './user-repository.js'; +import { User } from '../../entities/users/user.entity.js'; +import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; +// import { UserRepository } from './user-repository.js'; -export class StudentRepository extends UserRepository {} +// export class StudentRepository extends UserRepository {} + +export class StudentRepository extends DwengoEntityRepository { + public findByUsername(username: string): Promise { + return this.findOne({ username: username }); + } + public deleteByUsername(username: string): Promise { + return this.deleteWhere({ username: username }); + } +} \ No newline at end of file diff --git a/backend/src/data/users/teacher-repository.ts b/backend/src/data/users/teacher-repository.ts index 4c4f7687..23ba559e 100644 --- a/backend/src/data/users/teacher-repository.ts +++ b/backend/src/data/users/teacher-repository.ts @@ -1,4 +1,12 @@ import { Teacher } from '../../entities/users/teacher.entity.js'; +import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { UserRepository } from './user-repository.js'; -export class TeacherRepository extends UserRepository {} +export class TeacherRepository extends DwengoEntityRepository { + public findByUsername(username: string): Promise { + return this.findOne({ username: username }); + } + public deleteByUsername(username: string): Promise { + return this.deleteWhere({ username: username }); + } +} \ No newline at end of file diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index ecb02b90..015dcdc5 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -1,4 +1,5 @@ import { + Collection, Entity, Enum, ManyToOne, @@ -50,5 +51,5 @@ export class Assignment { }, mappedBy: 'assignment', }) - groups!: Group[]; + groups!: Collection; } diff --git a/backend/src/entities/assignments/group.entity.ts b/backend/src/entities/assignments/group.entity.ts index 0db4f6b0..446c0c0d 100644 --- a/backend/src/entities/assignments/group.entity.ts +++ b/backend/src/entities/assignments/group.entity.ts @@ -1,4 +1,4 @@ -import { Entity, ManyToMany, ManyToOne, PrimaryKey } from '@mikro-orm/core'; +import { Collection, Entity, ManyToMany, ManyToOne, PrimaryKey } from '@mikro-orm/core'; import { Assignment } from './assignment.entity.js'; import { Student } from '../users/student.entity.js'; import { GroupRepository } from '../../data/assignments/group-repository.js'; @@ -20,10 +20,8 @@ export class Group { @PrimaryKey({ type: 'integer', autoincrement: true }) groupNumber?: number; - @ManyToMany({ - entity: () => { - return Student; - }, + @ManyToMany(() => { + return Student; }) - members!: Student[]; + members!: Collection; } diff --git a/backend/src/entities/users/student.entity.ts b/backend/src/entities/users/student.entity.ts index 7ad8c9b3..c5632e84 100644 --- a/backend/src/entities/users/student.entity.ts +++ b/backend/src/entities/users/student.entity.ts @@ -19,4 +19,12 @@ export class Student extends User { return Group; }) groups!: Collection; + + constructor( + public username: string, + public firstName: string, + public lastName: string + ) { + super(); + } } diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index 65e111fb..2f2d0a14 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -83,14 +83,11 @@ export async function createGroup( const groupRepository = getGroupRepository(); try { - console.log('EEEEE'); const newGroup = groupRepository.create({ assignment: assignment, members: members, }); - console.log('OOOOOO'); await groupRepository.save(newGroup); - console.log('AAAAAA'); return newGroup; } catch(e) { From d9eb8def72ee94fcc82e130085c086b5c8de6a7c Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Thu, 13 Mar 2025 16:45:59 +0100 Subject: [PATCH 38/49] feat: submission route post delete --- backend/src/controllers/submissions.ts | 41 ++++++++++++++++---- backend/src/interfaces/submission.ts | 27 ++++++++++--- backend/src/interfaces/teacher-invitation.ts | 2 +- backend/src/routes/groups.ts | 2 +- backend/src/routes/submissions.ts | 6 ++- backend/src/services/submissions.ts | 39 ++++++++++++++++++- 6 files changed, 100 insertions(+), 17 deletions(-) diff --git a/backend/src/controllers/submissions.ts b/backend/src/controllers/submissions.ts index 572dae43..1a5da7ea 100644 --- a/backend/src/controllers/submissions.ts +++ b/backend/src/controllers/submissions.ts @@ -1,28 +1,29 @@ import { Request, Response } from "express"; -import { getSubmission } from "../services/submissions.js"; +import {createSubmission, deleteSubmission, getSubmission} from "../services/submissions.js"; import { Language, languageMap } from "../entities/content/language.js"; +import {SubmissionDTO} from "../interfaces/submission"; interface SubmissionParams { - lohruid: string, - submissionNumber: number; + hruid: string, + id: number; } export async function getSubmissionHandler( req: Request, res: Response, ): Promise { - const lohruid = req.params.lohruid; - const submissionNumber = +req.params.submissionNumber; + const lohruid = req.params.hruid; + const submissionNumber = +req.params.id; if (isNaN(submissionNumber)) { - res.status(404).json({ error: 'Submission number is not a number' }); + res.status(400).json({ error: 'Submission number is not a number' }); return; } let lang = languageMap[req.query.language as string] || Language.Dutch; let version = req.query.version as string || '1'; - const submission = getSubmission(lohruid, lang, version, submissionNumber); + const submission = await getSubmission(lohruid, lang, version, submissionNumber); if (!submission) { res.status(404).json({ error: 'Submission not found' }); @@ -31,3 +32,29 @@ export async function getSubmissionHandler( res.json(submission); } + +export async function createSubmissionHandler(req: Request, res: Response){ + const submissionDTO = req.body as SubmissionDTO; + + const submission = await createSubmission(submissionDTO); + + if (!submission) + res.status(404).json({ error: 'Submission not added' }); + else + res.json(submission) +} + +export async function deleteSubmissionHandler(req: Request, res: Response){ + const hruid = req.params.hruid; + const submissionNumber = +req.params.id; + + let lang = languageMap[req.query.language as string] || Language.Dutch; + let version = req.query.version as string || '1'; + + const submission = await deleteSubmission(hruid, lang, version, submissionNumber); + + if (!submission) + res.status(404).json({ error: 'Submission not found' }); + else + res.json(submission) +} diff --git a/backend/src/interfaces/submission.ts b/backend/src/interfaces/submission.ts index e0fddf07..b6227fc4 100644 --- a/backend/src/interfaces/submission.ts +++ b/backend/src/interfaces/submission.ts @@ -1,17 +1,19 @@ import { Submission } from "../entities/assignments/submission.entity.js"; import { Language } from "../entities/content/language.js"; import { GroupDTO, mapToGroupDTO } from "./group.js"; -import { mapToStudentDTO, StudentDTO } from "./student.js"; +import {mapToStudent, mapToStudentDTO, StudentDTO} from "./student.js"; +import {mapToUser} from "./user"; +import {Student} from "../entities/users/student.entity"; export interface SubmissionDTO { learningObjectHruid: string, learningObjectLanguage: Language, learningObjectVersion: string, - submissionNumber: number, - submitter: StudentDTO | string, - time: Date, - group?: GroupDTO | string, + submissionNumber?: number, + submitter: StudentDTO, + time?: Date, + group?: GroupDTO, content: string, } @@ -28,3 +30,18 @@ export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { content: submission.content, } } + +export function mapToSubmission(submissionDTO: SubmissionDTO): Submission { + const submission = new Submission(); + submission.learningObjectHruid = submissionDTO.learningObjectHruid; + submission.learningObjectLanguage = submissionDTO.learningObjectLanguage; + submission.learningObjectVersion = submissionDTO.learningObjectVersion; + // submission.submissionNumber = submissionDTO.submissionNumber; + submission.submitter = mapToStudent(submissionDTO.submitter) ; + // submission.submissionTime = submissionDTO.time; + // submission.onBehalfOf = submissionDTO.group!; + // TODO fix group + submission.content = submissionDTO.content; + + return submission; +} diff --git a/backend/src/interfaces/teacher-invitation.ts b/backend/src/interfaces/teacher-invitation.ts index badbbbd7..d29e7476 100644 --- a/backend/src/interfaces/teacher-invitation.ts +++ b/backend/src/interfaces/teacher-invitation.ts @@ -24,6 +24,6 @@ export function mapToTeacherInvitationDTOIds( return { sender: invitation.sender.username, receiver: invitation.receiver.username, - class: invitation.class.classId, + class: invitation.class.classId!, }; } diff --git a/backend/src/routes/groups.ts b/backend/src/routes/groups.ts index d17a330e..c2a462ca 100644 --- a/backend/src/routes/groups.ts +++ b/backend/src/routes/groups.ts @@ -12,7 +12,7 @@ router.get('/:groupid', getGroupHandler); router.get('/:groupid', getGroupSubmissionsHandler); // The list of questions a group has made -router.get('/:id/question', (req, res) => { +router.get('/:id/questions', (req, res) => { res.json({ questions: ['0'], }); diff --git a/backend/src/routes/submissions.ts b/backend/src/routes/submissions.ts index 1be419d4..e431260f 100644 --- a/backend/src/routes/submissions.ts +++ b/backend/src/routes/submissions.ts @@ -1,5 +1,5 @@ import express from 'express'; -import { getSubmissionHandler } from '../controllers/submissions.js'; +import {createSubmissionHandler, deleteSubmissionHandler, getSubmissionHandler} from '../controllers/submissions.js'; const router = express.Router({ mergeParams: true }); @@ -11,7 +11,11 @@ router.get('/', (req, res) => { }); }); +router.post('/:id', createSubmissionHandler); + // Information about an submission with id 'id' router.get('/:id', getSubmissionHandler); +router.delete('/:id', deleteSubmissionHandler); + export default router; diff --git a/backend/src/services/submissions.ts b/backend/src/services/submissions.ts index c805c717..bf30386b 100644 --- a/backend/src/services/submissions.ts +++ b/backend/src/services/submissions.ts @@ -1,7 +1,7 @@ -import { getSubmissionRepository } from "../data/repositories.js"; +import {getGroupRepository, getSubmissionRepository} from "../data/repositories.js"; import { Language } from "../entities/content/language.js"; import { LearningObjectIdentifier } from "../entities/content/learning-object-identifier.js"; -import { mapToSubmissionDTO, SubmissionDTO } from "../interfaces/submission.js"; +import {mapToSubmission, mapToSubmissionDTO, SubmissionDTO} from "../interfaces/submission.js"; export async function getSubmission( learningObjectHruid: string, @@ -20,3 +20,38 @@ export async function getSubmission( return mapToSubmissionDTO(submission); } + +export async function createSubmission(submissionDTO: SubmissionDTO) { + const submissionRepository = getSubmissionRepository(); + const submission = mapToSubmission(submissionDTO); + + try { + const newSubmission = await submissionRepository.create(submission); + await submissionRepository.save(newSubmission); + } catch (e) { + return null + } + + return submission; +} + +export async function deleteSubmission( + learningObjectHruid: string, + language: Language, + version: string, + submissionNumber: number +) { + const submissionRepository = getSubmissionRepository(); + + const submission = getSubmission(learningObjectHruid, language, version, submissionNumber); + + if (!submission) + return null + + const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); + await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(loId, submissionNumber); + + return submission; +} + + From b5390258e356323ad90404c4ed249693622909aa Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Thu, 13 Mar 2025 18:44:41 +0100 Subject: [PATCH 39/49] fix: import errors van gabe gefixt, teacher en student abstractie weggedaan --- backend/src/app.ts | 2 +- backend/src/controllers/questions.ts | 4 +- backend/src/controllers/students.ts | 89 +- backend/src/controllers/submissions.ts | 4 +- backend/src/controllers/teachers.ts | 109 +- backend/src/controllers/themes.ts | 2 +- .../content/learning-object-repository.ts | 9 + .../src/data/questions/question-repository.ts | 1 + backend/src/data/repositories.ts | 1 - .../entities/assignments/assignment.entity.ts | 2 +- .../src/entities/assignments/group.entity.ts | 1 + backend/src/entities/classes/class.entity.ts | 1 + .../src/entities/content/attachment.entity.ts | 1 + backend/src/entities/content/language.ts | 2 +- backend/src/interfaces/answer.ts | 2 +- backend/src/interfaces/question.ts | 6 +- backend/src/interfaces/student.ts | 9 +- backend/src/interfaces/submission.ts | 2 +- backend/src/interfaces/teacher.ts | 33 + backend/src/routes/learning-objects.ts | 2 + backend/src/services/learning-objects.ts | 7 +- .../dwengo-api-learning-object-provider.ts | 2 +- .../dwengo-api-learning-path-provider.ts | 2 +- backend/src/services/questions.ts | 3 +- backend/src/services/students.ts | 54 +- backend/src/services/submissions.ts | 4 +- backend/src/services/teachers.ts | 200 +- .../data/assignments/submissions.test.ts | 8 +- .../tests/data/content/attachments.test.ts | 4 +- .../data/content/learning-objects.test.ts | 4 +- backend/tests/data/questions/answers.test.ts | 6 +- .../tests/data/questions/questions.test.ts | 6 +- .../assignments/submission.testdata.ts | 10 +- .../content/learning-paths.testdata.ts | 4 +- .../questions/questions.testdata.ts | 8 +- package-lock.json | 9330 +++++++++++++++++ 36 files changed, 9754 insertions(+), 180 deletions(-) create mode 100644 backend/src/interfaces/teacher.ts create mode 100644 package-lock.json diff --git a/backend/src/app.ts b/backend/src/app.ts index 93de72bd..abb2bbbc 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -5,7 +5,7 @@ import themeRoutes from './routes/themes.js'; import learningPathRoutes from './routes/learning-paths.js'; import learningObjectRoutes from './routes/learning-objects.js'; -import studentRouter from './routes/student.js'; +import studentRouter from './routes/students.js'; import groupRouter from './routes/groups.js'; import assignmentRouter from './routes/assignments.js'; import submissionRouter from './routes/submissions.js'; diff --git a/backend/src/controllers/questions.ts b/backend/src/controllers/questions.ts index aa39853a..2b57f4c9 100644 --- a/backend/src/controllers/questions.ts +++ b/backend/src/controllers/questions.ts @@ -12,7 +12,7 @@ import {LearningObjectIdentifier} from "../entities/content/learning-object-iden import {Language} from "../entities/content/language.js"; function getObjectId(req: Request, res: Response): LearningObjectIdentifier | null { - const { hruid, version} = req.params + const { hruid, version } = req.params const lang = req.query.lang if (!hruid || !version ) { @@ -23,7 +23,7 @@ function getObjectId(req: Request, res: Response): LearningObjectIdentifier | nu return { hruid, language: lang as Language || FALLBACK_LANG, - version + version: +version } } diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 9a052a86..aae37b50 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,49 +1,106 @@ import { Request, Response } from 'express'; import { + createStudent, + deleteStudent, + getStudent, getStudentAssignments, getStudentClasses, getStudentGroups, getStudentSubmissions, - StudentService, } from '../services/students.js'; import { ClassDTO } from '../interfaces/class.js'; import { getAllAssignments } from '../services/assignments.js'; import { - createUserHandler, - deleteUserHandler, - getAllUsersHandler, getUserHandler, } from './users.js'; import { Student } from '../entities/users/student.entity.js'; +import { StudentDTO } from '../interfaces/student.js'; +import { getStudentRepository } from '../data/repositories.js'; +import { UserDTO } from '../interfaces/user.js'; // TODO: accept arguments (full, ...) // TODO: endpoints export async function getAllStudentsHandler( req: Request, - res: Response + res: Response, ): Promise { - await getAllUsersHandler(req, res, new StudentService()); + const full = req.query.full === 'true'; + + const studentRepository = getStudentRepository(); + + const students: StudentDTO[] | string[] = full + ? await getAllStudents() + : await getAllStudents(); + + if (!students) { + res.status(404).json({ error: `Student not found.` }); + return; + } + + res.status(201).json(students); } + export async function getStudentHandler( req: Request, - res: Response + res: Response, ): Promise { - await getUserHandler(req, res, new StudentService()); + const username = req.params.username; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + const user = await getStudent(username); + + if (!user) { + res.status(404).json({ + error: `User with username '${username}' not found.`, + }); + return; + } + + res.status(201).json(user); } export async function createStudentHandler( req: Request, - res: Response -): Promise { - await createUserHandler(req, res, new StudentService(), Student); + res: Response, +) { + const userData = req.body as StudentDTO; + + if (!userData.username || !userData.firstName || !userData.lastName) { + res.status(400).json({ + error: 'Missing required fields: username, firstName, lastName', + }); + return; + } + + const newUser = await createStudent(userData); + res.status(201).json(newUser); } export async function deleteStudentHandler( req: Request, - res: Response -): Promise { - await deleteUserHandler(req, res, new StudentService()); + res: Response, +) { + const username = req.params.username; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + const deletedUser = await deleteStudent(username); + if (!deletedUser) { + res.status(404).json({ + error: `User with username '${username}' not found.`, + }); + return; + } + + res.status(200).json(deletedUser); } export async function getStudentClassesHandler( @@ -115,3 +172,7 @@ export async function getStudentSubmissionsHandler( submissions: submissions, }); } +function getAllStudents(): StudentDTO[] | string[] | PromiseLike { + throw new Error('Function not implemented.'); +} + diff --git a/backend/src/controllers/submissions.ts b/backend/src/controllers/submissions.ts index 1a5da7ea..4080d1e7 100644 --- a/backend/src/controllers/submissions.ts +++ b/backend/src/controllers/submissions.ts @@ -21,7 +21,7 @@ export async function getSubmissionHandler( } let lang = languageMap[req.query.language as string] || Language.Dutch; - let version = req.query.version as string || '1'; + let version = (req.query.version || 1) as number; const submission = await getSubmission(lohruid, lang, version, submissionNumber); @@ -49,7 +49,7 @@ export async function deleteSubmissionHandler(req: Request, res: Response){ const submissionNumber = +req.params.id; let lang = languageMap[req.query.language as string] || Language.Dutch; - let version = req.query.version as string || '1'; + let version = (req.query.version || 1) as number; const submission = await deleteSubmission(hruid, lang, version, submissionNumber); diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index c083710d..02846fd9 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -1,49 +1,96 @@ import { Request, Response } from 'express'; -import { TeacherUserService, TeacherService } from '../services/teachers.js'; +import { createTeacher, deleteTeacher, getAllTeachers, getClassesByTeacher, getClassIdsByTeacher, getQuestionIdsByTeacher, getQuestionsByTeacher, getStudentIdsByTeacher, getStudentsByTeacher, getTeacher } from '../services/teachers.js'; import { ClassDTO } from '../interfaces/class.js'; import { StudentDTO } from '../interfaces/student.js'; import { QuestionDTO, QuestionId } from '../interfaces/question.js'; -import { - createUserHandler, - deleteUserHandler, - getAllUsersHandler, - getUserHandler, -} from './users.js'; import { Teacher } from '../entities/users/teacher.entity.js'; +import { TeacherDTO } from '../interfaces/teacher.js'; +import { getTeacherRepository } from '../data/repositories.js'; export async function getAllTeachersHandler( req: Request, - res: Response + res: Response, ): Promise { - await getAllUsersHandler(req, res, new TeacherUserService()); + const full = req.query.full === 'true'; + + const teacherRepository = getTeacherRepository(); + + const teachers: TeacherDTO[] | string[] = full + ? await getAllTeachers() + : await getAllTeachers(); + + if (!teachers) { + res.status(404).json({ error: `Teacher not found.` }); + return; + } + + res.status(201).json(teachers); } + export async function getTeacherHandler( req: Request, - res: Response + res: Response, ): Promise { - await getUserHandler(req, res, new TeacherUserService()); + const username = req.params.username; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + const user = await getTeacher(username); + + if (!user) { + res.status(404).json({ + error: `User with username '${username}' not found.`, + }); + return; + } + + res.status(201).json(user); } export async function createTeacherHandler( req: Request, - res: Response -): Promise { - await createUserHandler( - req, - res, - new TeacherUserService(), - Teacher - ); + res: Response, +) { + const userData = req.body as TeacherDTO; + + if (!userData.username || !userData.firstName || !userData.lastName) { + res.status(400).json({ + error: 'Missing required fields: username, firstName, lastName', + }); + return; + } + + const newUser = await createTeacher(userData); + res.status(201).json(newUser); } export async function deleteTeacherHandler( req: Request, - res: Response -): Promise { - await deleteUserHandler(req, res, new TeacherUserService()); + res: Response, +) { + const username = req.params.username; + + if (!username) { + res.status(400).json({ error: 'Missing required field: username' }); + return; + } + + const deletedUser = await deleteTeacher(username); + if (!deletedUser) { + res.status(404).json({ + error: `User with username '${username}' not found.`, + }); + return; + } + + res.status(200).json(deletedUser); } + export async function getTeacherClassHandler( req: Request, res: Response @@ -57,11 +104,9 @@ export async function getTeacherClassHandler( return; } - const teacherService = new TeacherService(); - const classes: ClassDTO[] | string[] = full - ? await teacherService.getClassesByTeacher(username) - : await teacherService.getClassIdsByTeacher(username); + ? await getClassesByTeacher(username) + : await getClassIdsByTeacher(username); res.status(201).json(classes); } catch (error) { @@ -83,11 +128,9 @@ export async function getTeacherStudentHandler( return; } - const teacherService = new TeacherService(); - const students: StudentDTO[] | string[] = full - ? await teacherService.getStudentsByTeacher(username) - : await teacherService.getStudentIdsByTeacher(username); + ? await getStudentsByTeacher(username) + : await getStudentIdsByTeacher(username); res.status(201).json(students); } catch (error) { @@ -109,11 +152,9 @@ export async function getTeacherQuestionHandler( return; } - const teacherService = new TeacherService(); - const questions: QuestionDTO[] | QuestionId[] = full - ? await teacherService.getQuestionsByTeacher(username) - : await teacherService.getQuestionIdsByTeacher(username); + ? await getQuestionsByTeacher(username) + : await getQuestionIdsByTeacher(username); res.status(201).json(questions); } catch (error) { diff --git a/backend/src/controllers/themes.ts b/backend/src/controllers/themes.ts index fe1eb818..61a1a834 100644 --- a/backend/src/controllers/themes.ts +++ b/backend/src/controllers/themes.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; import { themes } from '../data/themes.js'; -import { loadTranslations } from '../util/translationHelper.js'; +import { loadTranslations } from '../util/translation-helper.js'; interface Translations { curricula_page: { diff --git a/backend/src/data/content/learning-object-repository.ts b/backend/src/data/content/learning-object-repository.ts index 2b544533..49b4c536 100644 --- a/backend/src/data/content/learning-object-repository.ts +++ b/backend/src/data/content/learning-object-repository.ts @@ -1,6 +1,8 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { LearningObject } from '../../entities/content/learning-object.entity.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; +import { Language } from '../../entities/content/language.js'; +import { Teacher } from '../../entities/users/teacher.entity.js'; export class LearningObjectRepository extends DwengoEntityRepository { public findByIdentifier(identifier: LearningObjectIdentifier): Promise { @@ -30,4 +32,11 @@ export class LearningObjectRepository extends DwengoEntityRepository { + return this.find( + { admins: teacher }, + { populate: ['admins'] } // Make sure to load admin relations + ); + } } diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index d65d4575..dc8502d1 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -2,6 +2,7 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Question } from '../../entities/questions/question.entity.js'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier.js'; import { Student } from '../../entities/users/student.entity.js'; +import { LearningObject } from '../../entities/content/learning-object.entity.js'; export class QuestionRepository extends DwengoEntityRepository { public createQuestion(question: { loId: LearningObjectIdentifier; author: Student; content: string }): Promise { diff --git a/backend/src/data/repositories.ts b/backend/src/data/repositories.ts index 31269611..0c091aa9 100644 --- a/backend/src/data/repositories.ts +++ b/backend/src/data/repositories.ts @@ -56,7 +56,6 @@ function repositoryGetter>( } /* Users */ -export const getUserRepository = repositoryGetter(User); export const getStudentRepository = repositoryGetter(Student); export const getTeacherRepository = repositoryGetter(Teacher); diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index 015dcdc5..4992cca4 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -51,5 +51,5 @@ export class Assignment { }, mappedBy: 'assignment', }) - groups!: Collection; + groups!: Group[]; } diff --git a/backend/src/entities/assignments/group.entity.ts b/backend/src/entities/assignments/group.entity.ts index 45065db6..a961ed53 100644 --- a/backend/src/entities/assignments/group.entity.ts +++ b/backend/src/entities/assignments/group.entity.ts @@ -1,6 +1,7 @@ import { Collection, Entity, ManyToMany, ManyToOne, PrimaryKey } from '@mikro-orm/core'; import { Assignment } from './assignment.entity.js'; import { Student } from '../users/student.entity.js'; +import { GroupRepository } from '../../data/assignments/group-repository.js'; @Entity({ repository: () => { diff --git a/backend/src/entities/classes/class.entity.ts b/backend/src/entities/classes/class.entity.ts index 00079c85..a2c016ef 100644 --- a/backend/src/entities/classes/class.entity.ts +++ b/backend/src/entities/classes/class.entity.ts @@ -8,6 +8,7 @@ import { import { v4 } from 'uuid'; import { Teacher } from '../users/teacher.entity.js'; import { Student } from '../users/student.entity.js'; +import { ClassRepository } from '../../data/classes/class-repository.js'; @Entity({ repository: () => { diff --git a/backend/src/entities/content/attachment.entity.ts b/backend/src/entities/content/attachment.entity.ts index 08497b58..3903f055 100644 --- a/backend/src/entities/content/attachment.entity.ts +++ b/backend/src/entities/content/attachment.entity.ts @@ -1,5 +1,6 @@ import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; import { LearningObject } from './learning-object.entity.js'; +import { AttachmentRepository } from '../../data/content/attachment-repository.js'; @Entity({ repository: () => { diff --git a/backend/src/entities/content/language.ts b/backend/src/entities/content/language.ts index 30331683..40a00919 100644 --- a/backend/src/entities/content/language.ts +++ b/backend/src/entities/content/language.ts @@ -189,5 +189,5 @@ export const languageMap: Record = { nl: Language.Dutch, fr: Language.French, en: Language.English, - de: Language.Germany, + de: Language.German, }; \ No newline at end of file diff --git a/backend/src/interfaces/answer.ts b/backend/src/interfaces/answer.ts index 1b363c0d..0b86a4d1 100644 --- a/backend/src/interfaces/answer.ts +++ b/backend/src/interfaces/answer.ts @@ -17,7 +17,7 @@ export function mapToAnswerDTO(answer: Answer): AnswerDTO { return { author: mapToUserDTO(answer.author), toQuestion: mapToQuestionDTO(answer.toQuestion), - sequenceNumber: answer.sequenceNumber, + sequenceNumber: answer.sequenceNumber!, timestamp: answer.timestamp.toISOString(), content: answer.content, }; diff --git a/backend/src/interfaces/question.ts b/backend/src/interfaces/question.ts index 23c3edea..69039ee9 100644 --- a/backend/src/interfaces/question.ts +++ b/backend/src/interfaces/question.ts @@ -1,11 +1,13 @@ import { Question } from '../entities/questions/question.entity.js'; import {UserDTO} from "./user.js"; import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; +import { mapToStudentDTO, StudentDTO } from './student.js'; +import { TeacherDTO } from './teacher.js'; export interface QuestionDTO { learningObjectIdentifier: LearningObjectIdentifier; sequenceNumber?: number; - author: UserDTO; + author: StudentDTO; timestamp?: string; content: string; } @@ -23,7 +25,7 @@ export function mapToQuestionDTO(question: Question): QuestionDTO { return { learningObjectIdentifier, sequenceNumber: question.sequenceNumber!, - author: question.author, + author: mapToStudentDTO(question.author), timestamp: question.timestamp.toISOString(), content: question.content, }; diff --git a/backend/src/interfaces/student.ts b/backend/src/interfaces/student.ts index 529c6ead..9790eb35 100644 --- a/backend/src/interfaces/student.ts +++ b/backend/src/interfaces/student.ts @@ -23,10 +23,11 @@ export function mapToStudentDTO(student: Student): StudentDTO { } export function mapToStudent(studentData: StudentDTO): Student { - const student = new Student(); - student.username = studentData.username; - student.firstName = studentData.firstName; - student.lastName = studentData.lastName; + const student = new Student( + studentData.username, + studentData.firstName, + studentData.lastName, + ); return student; } diff --git a/backend/src/interfaces/submission.ts b/backend/src/interfaces/submission.ts index b6227fc4..2400075f 100644 --- a/backend/src/interfaces/submission.ts +++ b/backend/src/interfaces/submission.ts @@ -8,7 +8,7 @@ import {Student} from "../entities/users/student.entity"; export interface SubmissionDTO { learningObjectHruid: string, learningObjectLanguage: Language, - learningObjectVersion: string, + learningObjectVersion: number, submissionNumber?: number, submitter: StudentDTO, diff --git a/backend/src/interfaces/teacher.ts b/backend/src/interfaces/teacher.ts new file mode 100644 index 00000000..93dbf5fd --- /dev/null +++ b/backend/src/interfaces/teacher.ts @@ -0,0 +1,33 @@ +import { Teacher } from '../entities/users/teacher.entity.js'; + +export interface TeacherDTO { + id: string; + username: string; + firstName: string; + lastName: string; + endpoints?: { + classes: string; + questions: string; + invitations: string; + groups: string; + }; +} + +export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { + return { + id: teacher.username, + username: teacher.username, + firstName: teacher.firstName, + lastName: teacher.lastName, + }; +} + +export function mapToTeacher(TeacherData: TeacherDTO): Teacher { + const teacher = new Teacher( + TeacherData.username, + TeacherData.firstName, + TeacherData.lastName, + ); + + return teacher; +} diff --git a/backend/src/routes/learning-objects.ts b/backend/src/routes/learning-objects.ts index 3f598509..45e0df4c 100644 --- a/backend/src/routes/learning-objects.ts +++ b/backend/src/routes/learning-objects.ts @@ -1,7 +1,9 @@ import express from 'express'; import { getAllLearningObjects, + getAttachment, getLearningObject, + getLearningObjectHTML, } from '../controllers/learning-objects.js'; import submissionRoutes from './submissions.js'; diff --git a/backend/src/services/learning-objects.ts b/backend/src/services/learning-objects.ts index 65ad11a6..4f7d66a8 100644 --- a/backend/src/services/learning-objects.ts +++ b/backend/src/services/learning-objects.ts @@ -5,8 +5,7 @@ import { LearningObjectMetadata, LearningObjectNode, LearningPathResponse, -} from '../interfaces/learning-path.js'; -import { fetchLearningPaths } from './learning-paths.js'; +} from '../interfaces/learning-content.js'; function filterData( data: LearningObjectMetadata, @@ -132,3 +131,7 @@ export async function getLearningObjectIdsFromPath( ): Promise { return (await fetchLearningObjects(hruid, false, language)) as string[]; } +function fetchLearningPaths(arg0: string[], language: string, arg2: string): LearningPathResponse | PromiseLike { + throw new Error('Function not implemented.'); +} + diff --git a/backend/src/services/learning-objects/dwengo-api-learning-object-provider.ts b/backend/src/services/learning-objects/dwengo-api-learning-object-provider.ts index 37e68c07..dfee329d 100644 --- a/backend/src/services/learning-objects/dwengo-api-learning-object-provider.ts +++ b/backend/src/services/learning-objects/dwengo-api-learning-object-provider.ts @@ -1,5 +1,5 @@ import { DWENGO_API_BASE } from '../../config.js'; -import { fetchWithLogging } from '../../util/apiHelper.js'; +import { fetchWithLogging } from '../../util/api-helper.js'; import { FilteredLearningObject, LearningObjectIdentifier, diff --git a/backend/src/services/learning-paths/dwengo-api-learning-path-provider.ts b/backend/src/services/learning-paths/dwengo-api-learning-path-provider.ts index 2b1d17a6..a6093bb4 100644 --- a/backend/src/services/learning-paths/dwengo-api-learning-path-provider.ts +++ b/backend/src/services/learning-paths/dwengo-api-learning-path-provider.ts @@ -1,4 +1,4 @@ -import { fetchWithLogging } from '../../util/apiHelper.js'; +import { fetchWithLogging } from '../../util/api-helper.js'; import { DWENGO_API_BASE } from '../../config.js'; import { LearningPath, LearningPathResponse } from '../../interfaces/learning-content.js'; import { LearningPathProvider } from './learning-path-provider.js'; diff --git a/backend/src/services/questions.ts b/backend/src/services/questions.ts index a2fa01c6..6be684f9 100644 --- a/backend/src/services/questions.ts +++ b/backend/src/services/questions.ts @@ -7,6 +7,7 @@ import {QuestionRepository} from "../data/questions/question-repository.js"; import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; import {mapToUser} from "../interfaces/user.js"; import {Student} from "../entities/users/student.entity.js"; +import { mapToStudent } from "../interfaces/student.js"; export async function getAllQuestions( id: LearningObjectIdentifier, full: boolean @@ -72,7 +73,7 @@ export async function getAnswersByQuestion(questionId: QuestionId, full: boolean export async function createQuestion(questionDTO: QuestionDTO) { const questionRepository = getQuestionRepository(); - const author = mapToUser(questionDTO.author, new Student()) + const author = mapToStudent(questionDTO.author); try { await questionRepository.createQuestion({ diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 602ee4e1..4fc5c895 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -9,13 +9,61 @@ import { Student } from '../entities/users/student.entity.js'; import { AssignmentDTO } from '../interfaces/assignment.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; +import { mapToStudent, mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; import { getAllAssignments } from './assignments.js'; import { UserService } from './users.js'; -export class StudentService extends UserService { - constructor() { - super(getStudentRepository()); + +export async function getAllStudents(): Promise { + const studentRepository = getStudentRepository(); + const users = await studentRepository.findAll(); + return users.map(mapToStudentDTO); +} + +export async function getAllStudentIds(): Promise { + const users = await getAllStudents(); + return users.map((user) => { + return user.username; + }); +} + +export async function getStudent(username: string): Promise { + const studentRepository = getStudentRepository(); + const user = await studentRepository.findByUsername(username); + return user ? mapToStudentDTO(user) : null; +} + +export async function createStudent(userData: StudentDTO): Promise { + const studentRepository = getStudentRepository(); + + try { + const newStudent = studentRepository.create(mapToStudent(userData)); + await studentRepository.save(newStudent); + + return mapToStudentDTO(newStudent); + } catch(e) { + console.log(e); + return null; + } +} + +export async function deleteStudent(username: string): Promise { + const studentRepository = getStudentRepository(); + + const user = await studentRepository.findByUsername(username); + + if (!user) { + return null; + } + + try { + await studentRepository.deleteByUsername(username); + + return mapToStudentDTO(user); + } catch(e) { + console.log(e); + return null; } } diff --git a/backend/src/services/submissions.ts b/backend/src/services/submissions.ts index bf30386b..ce6f7bff 100644 --- a/backend/src/services/submissions.ts +++ b/backend/src/services/submissions.ts @@ -6,7 +6,7 @@ import {mapToSubmission, mapToSubmissionDTO, SubmissionDTO} from "../interfaces/ export async function getSubmission( learningObjectHruid: string, language: Language, - version: string, + version: number, submissionNumber: number, ): Promise { const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); @@ -38,7 +38,7 @@ export async function createSubmission(submissionDTO: SubmissionDTO) { export async function deleteSubmission( learningObjectHruid: string, language: Language, - version: string, + version: number, submissionNumber: number ) { const submissionRepository = getSubmissionRepository(); diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index b87c3b92..12325857 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -17,93 +17,133 @@ import { } from '../interfaces/question.js'; import { UserService } from './users.js'; import { mapToUser } from '../interfaces/user.js'; +import { mapToTeacher, mapToTeacherDTO, TeacherDTO } from '../interfaces/teacher.js'; -export class TeacherUserService extends UserService { - constructor() { - super(getTeacherRepository()); +export async function getAllTeachers(): Promise { + const teacherRepository = getTeacherRepository(); + const users = await teacherRepository.findAll(); + return users.map(mapToTeacherDTO); +} + +export async function getAllTeacherIds(): Promise { + const users = await getAllTeachers(); + return users.map((user) => { + return user.username; + }); +} + +export async function getTeacher(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const user = await teacherRepository.findByUsername(username); + return user ? mapToTeacherDTO(user) : null; +} + +export async function createTeacher(userData: TeacherDTO): Promise { + const teacherRepository = getTeacherRepository(); + + try { + const newTeacher = teacherRepository.create(mapToTeacher(userData)); + await teacherRepository.save(newTeacher); + + return mapToTeacherDTO(newTeacher); + } catch(e) { + console.log(e); + return null; } } -export class TeacherService { - protected teacherService = new TeacherUserService(); - protected teacherRepository = getTeacherRepository(); - protected classRepository = getClassRepository(); - protected learningObjectRepository = getLearningObjectRepository(); - protected questionRepository = getQuestionRepository(); +export async function deleteTeacher(username: string): Promise { + const teacherRepository = getTeacherRepository(); - async fetchClassesByTeacher(username: string): Promise { - const teacher = await this.teacherRepository.findByUsername(username); - if (!teacher) { - return []; - } + const user = await teacherRepository.findByUsername(username); - const classes = await this.classRepository.findByTeacher(teacher); - return classes.map(mapToClassDTO); + if (!user) { + return null; } - async getClassesByTeacher(username: string): Promise { - return await this.fetchClassesByTeacher(username); - } - - async getClassIdsByTeacher(username: string): Promise { - const classes = await this.fetchClassesByTeacher(username); - return classes.map((cls) => { - return cls.id; - }); - } - - async fetchStudentsByTeacher(username: string) { - const classes = await this.getClassIdsByTeacher(username); - - return ( - await Promise.all( - classes.map(async (id) => { - return getClassStudents(id); - }) - ) - ).flat(); - } - - async getStudentsByTeacher(username: string): Promise { - return await this.fetchStudentsByTeacher(username); - } - - async getStudentIdsByTeacher(username: string): Promise { - const students = await this.fetchStudentsByTeacher(username); - return students.map((student) => { - return student.username; - }); - } - - async fetchTeacherQuestions(username: string): Promise { - const teacherDTO = - await this.teacherService.getUserByUsername(username); - if (!teacherDTO) { - throw new Error(`Teacher with username '${username}' not found.`); - } - - const teacher = mapToUser(teacherDTO, new Teacher()); - - // Find all learning objects that this teacher manages - const learningObjects = - await this.learningObjectRepository.findAllByTeacher(teacher); - - // Fetch all questions related to these learning objects - const questions = - await this.questionRepository.findAllByLearningObjects( - learningObjects - ); - - return questions.map(mapToQuestionDTO); - } - - async getQuestionsByTeacher(username: string): Promise { - return await this.fetchTeacherQuestions(username); - } - - async getQuestionIdsByTeacher(username: string): Promise { - const questions = await this.fetchTeacherQuestions(username); - - return questions.map(mapToQuestionId); + try { + await teacherRepository.deleteByUsername(username); + + return mapToTeacherDTO(user); + } catch(e) { + console.log(e); + return null; } } + +export async function fetchClassesByTeacher(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const teacher = await teacherRepository.findByUsername(username); + if (!teacher) { + return []; + } + + const classRepository = getClassRepository(); + const classes = await classRepository.findByTeacher(teacher); + return classes.map(mapToClassDTO); +} + +export async function getClassesByTeacher(username: string): Promise { + return await fetchClassesByTeacher(username); +} + +export async function getClassIdsByTeacher(username: string): Promise { + const classes = await fetchClassesByTeacher(username); + return classes.map((cls) => { + return cls.id; + }); +} + +export async function fetchStudentsByTeacher(username: string) { + const classes = await getClassIdsByTeacher(username); + + return ( + await Promise.all( + classes.map(async (id) => { + return getClassStudents(id); + }) + ) + ).flat(); +} + +export async function getStudentsByTeacher(username: string): Promise { + return await fetchStudentsByTeacher(username); +} + +export async function getStudentIdsByTeacher(username: string): Promise { + const students = await fetchStudentsByTeacher(username); + return students.map((student) => { + return student.username; + }); +} + +export async function fetchTeacherQuestions(username: string): Promise { + const teacherRepository = getTeacherRepository(); + const teacher = await teacherRepository.findByUsername(username); + if (!teacher) { + throw new Error(`Teacher with username '${username}' not found.`); + } + + // Find all learning objects that this teacher manages + const learningObjectRepository = getLearningObjectRepository(); + const learningObjects = await learningObjectRepository.findAllByTeacher(teacher); + + // Fetch all questions related to these learning objects + const questionRepository = getQuestionRepository(); + const questions = + await questionRepository.findAllByLearningObjects( + learningObjects + ); + + return questions.map(mapToQuestionDTO); +} + +export async function getQuestionsByTeacher(username: string): Promise { + return await fetchTeacherQuestions(username); +} + +export async function getQuestionIdsByTeacher(username: string): Promise { + const questions = await fetchTeacherQuestions(username); + + return questions.map(mapToQuestionId); +} diff --git a/backend/tests/data/assignments/submissions.test.ts b/backend/tests/data/assignments/submissions.test.ts index 8712a710..cd212b77 100644 --- a/backend/tests/data/assignments/submissions.test.ts +++ b/backend/tests/data/assignments/submissions.test.ts @@ -32,7 +32,7 @@ describe('SubmissionRepository', () => { }); it('should find the requested submission', async () => { - const id = new LearningObjectIdentifier('id03', Language.English, '1'); + const id = new LearningObjectIdentifier('id03', Language.English, 1); const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1); expect(submission).toBeTruthy(); @@ -40,7 +40,7 @@ describe('SubmissionRepository', () => { }); it('should find the most recent submission for a student', async () => { - const id = new LearningObjectIdentifier('id02', Language.English, '1'); + const id = new LearningObjectIdentifier('id02', Language.English, 1); const student = await studentRepository.findByUsername('Noordkaap'); const submission = await submissionRepository.findMostRecentSubmissionForStudent(id, student!); @@ -49,7 +49,7 @@ describe('SubmissionRepository', () => { }); it('should find the most recent submission for a group', async () => { - const id = new LearningObjectIdentifier('id03', Language.English, '1'); + const id = new LearningObjectIdentifier('id03', Language.English, 1); const class_ = await classRepository.findById('id01'); const assignment = await assignmentRepository.findByClassAndId(class_!, 1); const group = await groupRepository.findByAssignmentAndGroupNumber(assignment!, 1); @@ -60,7 +60,7 @@ describe('SubmissionRepository', () => { }); it('should not find a deleted submission', async () => { - const id = new LearningObjectIdentifier('id01', Language.English, '1'); + const id = new LearningObjectIdentifier('id01', Language.English, 1); await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(id, 1); const submission = await submissionRepository.findSubmissionByLearningObjectAndSubmissionNumber(id, 1); diff --git a/backend/tests/data/content/attachments.test.ts b/backend/tests/data/content/attachments.test.ts index a8bea88a..94e132a9 100644 --- a/backend/tests/data/content/attachments.test.ts +++ b/backend/tests/data/content/attachments.test.ts @@ -17,11 +17,11 @@ describe('AttachmentRepository', () => { }); it('should return the requested attachment', async () => { - const id = new LearningObjectIdentifier('id02', Language.English, '1'); + const id = new LearningObjectIdentifier('id02', Language.English, 1); const learningObject = await learningObjectRepository.findByIdentifier(id); const attachment = await attachmentRepository.findByMostRecentVersionOfLearningObjectAndName( - learningObject!, + learningObject!.hruid, Language.English, 'attachment01' ); diff --git a/backend/tests/data/content/learning-objects.test.ts b/backend/tests/data/content/learning-objects.test.ts index 51f9c98e..712f75c9 100644 --- a/backend/tests/data/content/learning-objects.test.ts +++ b/backend/tests/data/content/learning-objects.test.ts @@ -13,8 +13,8 @@ describe('LearningObjectRepository', () => { learningObjectRepository = getLearningObjectRepository(); }); - const id01 = new LearningObjectIdentifier('id01', Language.English, '1'); - const id02 = new LearningObjectIdentifier('test_id', Language.English, '1'); + const id01 = new LearningObjectIdentifier('id01', Language.English, 1); + const id02 = new LearningObjectIdentifier('test_id', Language.English, 1); it('should return the learning object that matches identifier 1', async () => { const learningObject = await learningObjectRepository.findByIdentifier(id01); diff --git a/backend/tests/data/questions/answers.test.ts b/backend/tests/data/questions/answers.test.ts index f15fed6a..bcc62cf6 100644 --- a/backend/tests/data/questions/answers.test.ts +++ b/backend/tests/data/questions/answers.test.ts @@ -20,7 +20,7 @@ describe('AnswerRepository', () => { }); it('should find all answers to a question', async () => { - const id = new LearningObjectIdentifier('id05', Language.English, '1'); + const id = new LearningObjectIdentifier('id05', Language.English, 1); const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); const question = questions.filter((it) => it.sequenceNumber == 2)[0]; @@ -35,7 +35,7 @@ describe('AnswerRepository', () => { it('should create an answer to a question', async () => { const teacher = await teacherRepository.findByUsername('FooFighters'); - const id = new LearningObjectIdentifier('id05', Language.English, '1'); + const id = new LearningObjectIdentifier('id05', Language.English, 1); const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); const question = questions[0]; @@ -54,7 +54,7 @@ describe('AnswerRepository', () => { }); it('should not find a removed answer', async () => { - const id = new LearningObjectIdentifier('id04', Language.English, '1'); + const id = new LearningObjectIdentifier('id04', Language.English, 1); const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); await answerRepository.removeAnswerByQuestionAndSequenceNumber(questions[0], 1); diff --git a/backend/tests/data/questions/questions.test.ts b/backend/tests/data/questions/questions.test.ts index 1a1cb034..7b408df4 100644 --- a/backend/tests/data/questions/questions.test.ts +++ b/backend/tests/data/questions/questions.test.ts @@ -20,7 +20,7 @@ describe('QuestionRepository', () => { }); it('should return all questions part of the given learning object', async () => { - const id = new LearningObjectIdentifier('id05', Language.English, '1'); + const id = new LearningObjectIdentifier('id05', Language.English, 1); const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); expect(questions).toBeTruthy(); @@ -28,7 +28,7 @@ describe('QuestionRepository', () => { }); it('should create new question', async () => { - const id = new LearningObjectIdentifier('id03', Language.English, '1'); + const id = new LearningObjectIdentifier('id03', Language.English, 1); const student = await studentRepository.findByUsername('Noordkaap'); await questionRepository.createQuestion({ loId: id, @@ -42,7 +42,7 @@ describe('QuestionRepository', () => { }); it('should not find removed question', async () => { - const id = new LearningObjectIdentifier('id04', Language.English, '1'); + const id = new LearningObjectIdentifier('id04', Language.English, 1); await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(id, 1); const question = await questionRepository.findAllQuestionsAboutLearningObject(id); diff --git a/backend/tests/test_assets/assignments/submission.testdata.ts b/backend/tests/test_assets/assignments/submission.testdata.ts index 058af70f..95dd65df 100644 --- a/backend/tests/test_assets/assignments/submission.testdata.ts +++ b/backend/tests/test_assets/assignments/submission.testdata.ts @@ -12,7 +12,7 @@ export function makeTestSubmissions( const submission01 = em.create(Submission, { learningObjectHruid: 'id03', learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, submissionNumber: 1, submitter: students[0], submissionTime: new Date(2025, 2, 20), @@ -23,7 +23,7 @@ export function makeTestSubmissions( const submission02 = em.create(Submission, { learningObjectHruid: 'id03', learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, submissionNumber: 2, submitter: students[0], submissionTime: new Date(2025, 2, 25), @@ -34,7 +34,7 @@ export function makeTestSubmissions( const submission03 = em.create(Submission, { learningObjectHruid: 'id02', learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, submissionNumber: 1, submitter: students[0], submissionTime: new Date(2025, 2, 20), @@ -44,7 +44,7 @@ export function makeTestSubmissions( const submission04 = em.create(Submission, { learningObjectHruid: 'id02', learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, submissionNumber: 2, submitter: students[0], submissionTime: new Date(2025, 2, 25), @@ -54,7 +54,7 @@ export function makeTestSubmissions( const submission05 = em.create(Submission, { learningObjectHruid: 'id01', learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, submissionNumber: 1, submitter: students[1], submissionTime: new Date(2025, 2, 20), diff --git a/backend/tests/test_assets/content/learning-paths.testdata.ts b/backend/tests/test_assets/content/learning-paths.testdata.ts index d2e65c9e..10de885c 100644 --- a/backend/tests/test_assets/content/learning-paths.testdata.ts +++ b/backend/tests/test_assets/content/learning-paths.testdata.ts @@ -77,7 +77,7 @@ export function makeTestLearningPaths(em: EntityManager>, students: Array): Array { const question01 = em.create(Question, { learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, learningObjectHruid: 'id05', sequenceNumber: 1, author: students[0], @@ -16,7 +16,7 @@ export function makeTestQuestions(em: EntityManager> const question02 = em.create(Question, { learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, learningObjectHruid: 'id05', sequenceNumber: 2, author: students[2], @@ -26,7 +26,7 @@ export function makeTestQuestions(em: EntityManager> const question03 = em.create(Question, { learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, learningObjectHruid: 'id04', sequenceNumber: 1, author: students[0], @@ -36,7 +36,7 @@ export function makeTestQuestions(em: EntityManager> const question04 = em.create(Question, { learningObjectLanguage: Language.English, - learningObjectVersion: '1', + learningObjectVersion: 1, learningObjectHruid: 'id01', sequenceNumber: 1, author: students[1], diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..1b16ec55 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,9330 @@ +{ + "name": "dwengo-1-monorepo", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dwengo-1-monorepo", + "version": "0.0.1", + "license": "MIT", + "workspaces": [ + "backend", + "frontend" + ], + "devDependencies": { + "@eslint/compat": "^1.2.6", + "@eslint/js": "^9.20.0", + "@types/eslint-config-prettier": "^6.11.3", + "@typescript-eslint/eslint-plugin": "^8.24.1", + "@typescript-eslint/parser": "^8.24.1", + "eslint": "^9.20.1", + "eslint-config-prettier": "^10.0.1", + "jiti": "^2.4.2", + "typescript-eslint": "^8.24.1" + } + }, + "backend": { + "name": "dwengo-1-backend", + "version": "0.0.1", + "dependencies": { + "@mikro-orm/core": "6.4.9", + "@mikro-orm/knex": "6.4.9", + "@mikro-orm/postgresql": "6.4.9", + "@mikro-orm/reflection": "6.4.9", + "@mikro-orm/sqlite": "6.4.9", + "axios": "^1.8.2", + "cors": "^2.8.5", + "cross": "^1.0.0", + "cross-env": "^7.0.3", + "dotenv": "^16.4.7", + "express": "^5.0.1", + "express-jwt": "^8.5.1", + "gift-pegjs": "^1.0.2", + "isomorphic-dompurify": "^2.22.0", + "js-yaml": "^4.1.0", + "jsonpath-plus": "^10.3.0", + "jwks-rsa": "^3.1.0", + "loki-logger-ts": "^1.0.2", + "marked": "^15.0.7", + "response-time": "^2.3.3", + "uuid": "^11.1.0", + "winston": "^3.17.0", + "winston-loki": "^6.1.3" + }, + "devDependencies": { + "@mikro-orm/cli": "6.4.9", + "@types/cors": "^2.8.17", + "@types/express": "^5.0.0", + "@types/js-yaml": "^4.0.9", + "@types/node": "^22.13.4", + "@types/response-time": "^2.3.8", + "globals": "^15.15.0", + "ts-node": "^10.9.2", + "tsx": "^4.19.3", + "typescript": "^5.7.3", + "vitest": "^3.0.6" + } + }, + "backend/node_modules/globals": { + "version": "15.15.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "frontend": { + "name": "dwengo-1-frontend", + "version": "0.0.1", + "dependencies": { + "axios": "^1.8.2", + "oidc-client-ts": "^3.1.0", + "vue": "^3.5.13", + "vue-router": "^4.5.0", + "vuetify": "^3.7.12" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tsconfig/node22": "^22.0.0", + "@types/jsdom": "^21.1.7", + "@types/node": "^22.13.4", + "@vitejs/plugin-vue": "^5.2.1", + "@vitest/eslint-plugin": "1.1.31", + "@vue/eslint-config-prettier": "^10.2.0", + "@vue/eslint-config-typescript": "^14.4.0", + "@vue/test-utils": "^2.4.6", + "@vue/tsconfig": "^0.7.0", + "eslint": "^9.20.1", + "eslint-plugin-playwright": "^2.2.0", + "eslint-plugin-vue": "^9.32.0", + "jsdom": "^26.0.0", + "npm-run-all2": "^7.0.2", + "typescript": "~5.7.3", + "vite": "^6.1.0", + "vite-plugin-vue-devtools": "^7.7.2", + "vitest": "^3.0.5", + "vue-tsc": "^2.2.2" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "2.8.3", + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.1", + "@csstools/css-color-parser": "^3.0.7", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.9", + "@babel/types": "^7.26.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.26.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.26.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.26.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.26.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.9", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.9" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-decorators": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.26.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.26.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.26.9", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.7", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.1", + "@csstools/css-calc": "^2.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.0", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.2.6", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.10.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/core": { + "version": "0.11.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.20.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.6", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.11.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "license": "MIT", + "optional": true + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jercle/yargonaut": { + "version": "1.1.5", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "chalk": "^4.1.2", + "figlet": "^1.5.2", + "parent-require": "^1.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@jsep-plugin/assignment": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", + "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsep-plugin/regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", + "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@mikro-orm/cli": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@mikro-orm/cli/-/cli-6.4.9.tgz", + "integrity": "sha512-LQzVsmar/0DoJkPGyz3OpB8pa9BCQtvYreEC71h0O+RcizppJjgBQNTkj5tJd2Iqvh4hSaMv6qTv0l5UK6F2Vw==", + "dev": true, + "dependencies": { + "@jercle/yargonaut": "1.1.5", + "@mikro-orm/core": "6.4.9", + "@mikro-orm/knex": "6.4.9", + "fs-extra": "11.3.0", + "tsconfig-paths": "4.2.0", + "yargs": "17.7.2" + }, + "bin": { + "mikro-orm": "cli", + "mikro-orm-esm": "esm" + }, + "engines": { + "node": ">= 18.12.0" + } + }, + "node_modules/@mikro-orm/core": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@mikro-orm/core/-/core-6.4.9.tgz", + "integrity": "sha512-osB2TbvSH4ZL1s62LCBQFAnxPqLycX5fakPHOoztudixqfbVD5QQydeGizJXMMh2zKP6vRCwIJy3MeSuFxPjHg==", + "dependencies": { + "dataloader": "2.2.3", + "dotenv": "16.4.7", + "esprima": "4.0.1", + "fs-extra": "11.3.0", + "globby": "11.1.0", + "mikro-orm": "6.4.9", + "reflect-metadata": "0.2.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/b4nan" + } + }, + "node_modules/@mikro-orm/knex": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@mikro-orm/knex/-/knex-6.4.9.tgz", + "integrity": "sha512-iGXJfe/TziVOQsWuxMIqkOpurysWzQA6kj3+FDtOkHJAijZhqhjSBnfUVHHY/JzU9o0M0rgLrDVJFry/uEaJEA==", + "dependencies": { + "fs-extra": "11.3.0", + "knex": "3.1.0", + "sqlstring": "2.3.3" + }, + "engines": { + "node": ">= 18.12.0" + }, + "peerDependencies": { + "@mikro-orm/core": "^6.0.0", + "better-sqlite3": "*", + "libsql": "*", + "mariadb": "*" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "libsql": { + "optional": true + }, + "mariadb": { + "optional": true + } + } + }, + "node_modules/@mikro-orm/postgresql": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@mikro-orm/postgresql/-/postgresql-6.4.9.tgz", + "integrity": "sha512-ZdVVFAL/TSbzpEmChGdH0oUpy2KiHLjNIeItZHRQgInn1X9p0qx28VVDR78p8qgRGkQ3LquxGTkvmWI0w7qi3A==", + "dependencies": { + "@mikro-orm/knex": "6.4.9", + "pg": "8.13.3", + "postgres-array": "3.0.4", + "postgres-date": "2.1.0", + "postgres-interval": "4.0.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "peerDependencies": { + "@mikro-orm/core": "^6.0.0" + } + }, + "node_modules/@mikro-orm/reflection": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@mikro-orm/reflection/-/reflection-6.4.9.tgz", + "integrity": "sha512-fgY7yLrcZm3J/8dv9reUC4PQo7C2muImU31jmzz1SxmNKPJFDJl7OzcDZlM5NOisXzsWUBrcNdCyuQiWViVc3A==", + "dependencies": { + "globby": "11.1.0", + "ts-morph": "25.0.1" + }, + "engines": { + "node": ">= 18.12.0" + }, + "peerDependencies": { + "@mikro-orm/core": "^6.0.0" + } + }, + "node_modules/@mikro-orm/sqlite": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@mikro-orm/sqlite/-/sqlite-6.4.9.tgz", + "integrity": "sha512-O7Jy/5DrTWpJI/3qkhRJHl+OcECx1N625LHDODAAauOK3+MJB/bj80TrvQhe6d/CHZMmvxZ7m2GzaL1NulKxRw==", + "dependencies": { + "@mikro-orm/knex": "6.4.9", + "fs-extra": "11.3.0", + "sqlite3": "5.1.7", + "sqlstring-sqlite": "0.1.1" + }, + "engines": { + "node": ">= 18.12.0" + }, + "peerDependencies": { + "@mikro-orm/core": "^6.0.0" + } + }, + "node_modules/@napi-rs/snappy-android-arm-eabi": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm-eabi/-/snappy-android-arm-eabi-7.2.2.tgz", + "integrity": "sha512-H7DuVkPCK5BlAr1NfSU8bDEN7gYs+R78pSHhDng83QxRnCLmVIZk33ymmIwurmoA1HrdTxbkbuNl+lMvNqnytw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-android-arm64": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm64/-/snappy-android-arm64-7.2.2.tgz", + "integrity": "sha512-2R/A3qok+nGtpVK8oUMcrIi5OMDckGYNoBLFyli3zp8w6IArPRfg1yOfVUcHvpUDTo9T7LOS1fXgMOoC796eQw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-darwin-arm64": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-arm64/-/snappy-darwin-arm64-7.2.2.tgz", + "integrity": "sha512-USgArHbfrmdbuq33bD5ssbkPIoT7YCXCRLmZpDS6dMDrx+iM7eD2BecNbOOo7/v1eu6TRmQ0xOzeQ6I/9FIi5g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-darwin-x64": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-x64/-/snappy-darwin-x64-7.2.2.tgz", + "integrity": "sha512-0APDu8iO5iT0IJKblk2lH0VpWSl9zOZndZKnBYIc+ei1npw2L5QvuErFOTeTdHBtzvUHASB+9bvgaWnQo4PvTQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-freebsd-x64": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-freebsd-x64/-/snappy-freebsd-x64-7.2.2.tgz", + "integrity": "sha512-mRTCJsuzy0o/B0Hnp9CwNB5V6cOJ4wedDTWEthsdKHSsQlO7WU9W1yP7H3Qv3Ccp/ZfMyrmG98Ad7u7lG58WXA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-arm-gnueabihf": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm-gnueabihf/-/snappy-linux-arm-gnueabihf-7.2.2.tgz", + "integrity": "sha512-v1uzm8+6uYjasBPcFkv90VLZ+WhLzr/tnfkZ/iD9mHYiULqkqpRuC8zvc3FZaJy5wLQE9zTDkTJN1IvUcZ+Vcg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-arm64-gnu": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-gnu/-/snappy-linux-arm64-gnu-7.2.2.tgz", + "integrity": "sha512-LrEMa5pBScs4GXWOn6ZYXfQ72IzoolZw5txqUHVGs8eK4g1HR9HTHhb2oY5ySNaKakG5sOgMsb1rwaEnjhChmQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-arm64-musl": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-musl/-/snappy-linux-arm64-musl-7.2.2.tgz", + "integrity": "sha512-3orWZo9hUpGQcB+3aTLW7UFDqNCQfbr0+MvV67x8nMNYj5eAeUtMmUE/HxLznHO4eZ1qSqiTwLbVx05/Socdlw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-x64-gnu": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-gnu/-/snappy-linux-x64-gnu-7.2.2.tgz", + "integrity": "sha512-jZt8Jit/HHDcavt80zxEkDpH+R1Ic0ssiVCoueASzMXa7vwPJeF4ZxZyqUw4qeSy7n8UUExomu8G8ZbP6VKhgw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-x64-musl": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-musl/-/snappy-linux-x64-musl-7.2.2.tgz", + "integrity": "sha512-Dh96IXgcZrV39a+Tej/owcd9vr5ihiZ3KRix11rr1v0MWtVb61+H1GXXlz6+Zcx9y8jM1NmOuiIuJwkV4vZ4WA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-win32-arm64-msvc": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-arm64-msvc/-/snappy-win32-arm64-msvc-7.2.2.tgz", + "integrity": "sha512-9No0b3xGbHSWv2wtLEn3MO76Yopn1U2TdemZpCaEgOGccz1V+a/1d16Piz3ofSmnA13HGFz3h9NwZH9EOaIgYA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-win32-ia32-msvc": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-ia32-msvc/-/snappy-win32-ia32-msvc-7.2.2.tgz", + "integrity": "sha512-QiGe+0G86J74Qz1JcHtBwM3OYdTni1hX1PFyLRo3HhQUSpmi13Bzc1En7APn+6Pvo7gkrcy81dObGLDSxFAkQQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-win32-x64-msvc": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-x64-msvc/-/snappy-win32-x64-msvc-7.2.2.tgz", + "integrity": "sha512-a43cyx1nK0daw6BZxVcvDEXxKMFLSBSDTAhsFD0VqSKcC7MGUBMaqyoWUcMiI7LBSz4bxUmxDWKfCYzpEmeb3w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@playwright/test": { + "version": "1.50.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.50.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.28", + "dev": true, + "license": "MIT" + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.34.8", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.34.8", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@ts-morph/common": { + "version": "0.26.1", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.3.2", + "minimatch": "^9.0.4", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node22": { + "version": "22.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint-config-prettier": { + "version": "6.11.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "license": "MIT" + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsdom": { + "version": "21.1.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.9.tgz", + "integrity": "sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" + }, + "node_modules/@types/node": { + "version": "22.13.4", + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/qs": { + "version": "6.9.18", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "license": "MIT" + }, + "node_modules/@types/response-time": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/response-time/-/response-time-2.3.8.tgz", + "integrity": "sha512-7qGaNYvdxc0zRab8oHpYx7AW17qj+G0xuag1eCrw3M2VWPJQ/HyKaaghWygiaOUl0y9x7QGQwppDpqLJ5V9pzw==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "optional": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.24.1", + "@typescript-eslint/type-utils": "8.24.1", + "@typescript-eslint/utils": "8.24.1", + "@typescript-eslint/visitor-keys": "8.24.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.24.1", + "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/typescript-estree": "8.24.1", + "@typescript-eslint/visitor-keys": "8.24.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/visitor-keys": "8.24.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.24.1", + "@typescript-eslint/utils": "8.24.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/visitor-keys": "8.24.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.24.1", + "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/typescript-estree": "8.24.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.24.1", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitest/eslint-plugin": { + "version": "1.1.31", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/utils": ">= 8.0", + "eslint": ">= 8.57.0", + "typescript": ">= 5.0.0", + "vitest": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.0.6", + "@vitest/utils": "3.0.6", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.0.6", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.0.6", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.0.6", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.0.6", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.11", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.11" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.11", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.11", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.2.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.2.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.6", + "@babel/types": "^7.25.6", + "@vue/babel-helper-vue-transform-on": "1.2.5", + "@vue/babel-plugin-resolve-type": "1.2.5", + "html-tags": "^3.3.1", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.2.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/parser": "^7.25.6", + "@vue/compiler-sfc": "^3.5.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.13", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.13", + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.48", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "license": "MIT" + }, + "node_modules/@vue/devtools-core": { + "version": "7.7.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.2", + "@vue/devtools-shared": "^7.7.2", + "mitt": "^3.0.1", + "nanoid": "^5.0.9", + "pathe": "^2.0.2", + "vite-hot-client": "^0.2.4" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-core/node_modules/nanoid": { + "version": "5.1.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.2", + "birpc": "^0.2.19", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.1" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.2", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "10.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.2" + }, + "peerDependencies": { + "eslint": ">= 8.21.0", + "prettier": ">= 3.0.0" + } + }, + "node_modules/@vue/eslint-config-typescript": { + "version": "14.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.23.0", + "fast-glob": "^3.3.3", + "typescript-eslint": "^8.23.0", + "vue-eslint-parser": "^9.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.10.0", + "eslint-plugin-vue": "^9.28.0", + "typescript": ">=4.8.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core": { + "version": "2.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "~2.4.11", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.13", + "@vue/runtime-core": "3.5.13", + "@vue/shared": "3.5.13", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13" + }, + "peerDependencies": { + "vue": "3.5.13" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.13", + "license": "MIT" + }, + "node_modules/@vue/test-utils": { + "version": "2.4.6", + "dev": true, + "license": "MIT", + "dependencies": { + "js-beautify": "^1.14.9", + "vue-component-type-helpers": "^2.0.0" + } + }, + "node_modules/@vue/tsconfig": { + "version": "0.7.0", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": "5.x", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/abbrev": { + "version": "3.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.3", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/alien-signals": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bindings": { + "version": "1.5.0", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/birpc": { + "version": "0.2.19", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.5.2", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.14.0", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "optional": true, + "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/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001700", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/code-block-writer": { + "version": "13.0.3", + "license": "MIT" + }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorette": { + "version": "2.0.19", + "license": "MIT" + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "devOptional": true, + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "license": "ISC", + "optional": true + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/cross": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cross/-/cross-1.0.0.tgz", + "integrity": "sha512-p6hXbCnjuIB4bhKWFeztQd7VwffgQP9zOBzUoiA8Lvi01RzQY0e7PbPFU/uqVPTM2stY7uCpVck1UTPpxhinMQ==" + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssstyle": { + "version": "4.2.1", + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^2.8.2", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/dataloader": { + "version": "2.2.3", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.0", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.5.0", + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/default-browser": { + "version": "5.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "license": "MIT", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dompurify": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", + "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/dwengo-1-backend": { + "resolved": "backend", + "link": true + }, + "node_modules/dwengo-1-frontend": { + "resolved": "frontend", + "link": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.102", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "license": "MIT", + "optional": true + }, + "node_modules/error-stack-parser-es": { + "version": "0.1.5", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.6.0", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.0", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.20.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.11.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.20.0", + "@eslint/plugin-kit": "^0.2.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.0.1", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "build/bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-playwright": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "workspaces": [ + "examples" + ], + "dependencies": { + "globals": "^13.23.0" + }, + "engines": { + "node": ">=16.6.0" + }, + "peerDependencies": { + "eslint": ">=8.40.0" + } + }, + "node_modules/eslint-plugin-playwright/node_modules/globals": { + "version": "13.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.32.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-vue/node_modules/globals": { + "version": "13.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/execa": { + "version": "9.5.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.3", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.0", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/expect-type": { + "version": "1.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/express": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.0.1", + "content-disposition": "^1.0.0", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "^1.2.1", + "debug": "4.3.6", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "^2.0.0", + "fresh": "2.0.0", + "http-errors": "2.0.0", + "merge-descriptors": "^2.0.0", + "methods": "~1.1.2", + "mime-types": "^3.0.0", + "on-finished": "2.4.1", + "once": "1.4.0", + "parseurl": "~1.3.3", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "router": "^2.0.0", + "safe-buffer": "5.2.1", + "send": "^1.1.0", + "serve-static": "^2.1.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "^2.0.0", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/express-jwt": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/express-jwt/-/express-jwt-8.5.1.tgz", + "integrity": "sha512-Dv6QjDLpR2jmdb8M6XQXiCcpEom7mK8TOqnr0/TngDKsG2DHVkO8+XnVxkJVN7BuS1I3OrGw6N8j5DaaGgkDRQ==", + "dependencies": { + "@types/jsonwebtoken": "^9", + "express-unless": "^2.1.3", + "jsonwebtoken": "^9.0.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/express-unless": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/express-unless/-/express-unless-2.1.3.tgz", + "integrity": "sha512-wj4tLMyCVYuIIKHGt0FhCtIViBcwzWejX0EjNxveAa6dG+0XBCQhMbx+PnkLkFCxLC69qoFrxds4pIyL88inaQ==" + }, + "node_modules/express/node_modules/debug": { + "version": "4.3.6", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.0", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, + "node_modules/figlet": { + "version": "1.8.0", + "dev": true, + "license": "MIT", + "bin": { + "figlet": "bin/index.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/figures": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/encodeurl": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "dev": true, + "license": "ISC" + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.2", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "11.3.0", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT", + "optional": true + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC", + "optional": true + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "9.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/getopts": { + "version": "2.3.0", + "license": "MIT" + }, + "node_modules/gift-pegjs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/gift-pegjs/-/gift-pegjs-1.0.2.tgz", + "integrity": "sha512-S/A2wBDdia2QWKpB5FtASx1gguep1wg5If5glDWJgUMiABICJT7ogArGfsdgozevhBdbdOiHhrykJP86hbgvRw==", + "dependencies": { + "pegjs": "^0.10.x" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "license": "MIT" + }, + "node_modules/glob": { + "version": "10.4.5", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "license": "ISC", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "dev": true, + "license": "MIT" + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "8.0.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.5.2", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "license": "ISC" + }, + "node_modules/interpret": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "license": "MIT", + "optional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "license": "MIT", + "optional": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/is-promise": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/isomorphic-dompurify": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/isomorphic-dompurify/-/isomorphic-dompurify-2.22.0.tgz", + "integrity": "sha512-A2xsDNST1yB94rErEnwqlzSvGllCJ4e8lDMe1OWBH2hvpfc/2qzgMEiDshTO1HwO+PIDTiYeOc7ZDB7Ds49BOg==", + "dependencies": { + "dompurify": "^3.2.4", + "jsdom": "^26.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jose": { + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-beautify": { + "version": "1.15.3", + "dev": true, + "license": "MIT", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^8.0.0" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "license": "MIT", + "optional": true + }, + "node_modules/jsdom": { + "version": "26.0.0", + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.1", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/xml-name-validator": { + "version": "5.0.0", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/jsep": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", + "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpath-plus": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz", + "integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==", + "dependencies": { + "@jsep-plugin/assignment": "^1.3.0", + "@jsep-plugin/regex": "^1.0.4", + "jsep": "^1.4.0" + }, + "bin": { + "jsonpath": "bin/jsonpath-cli.js", + "jsonpath-plus": "bin/jsonpath-cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwks-rsa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.1.0.tgz", + "integrity": "sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==", + "dependencies": { + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", + "debug": "^4.3.4", + "jose": "^4.14.6", + "limiter": "^1.1.5", + "lru-memoizer": "^2.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/jwks-rsa/node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/jwks-rsa/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/knex": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/knex/node_modules/resolve-from": { + "version": "5.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "dev": true, + "license": "MIT" + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "node_modules/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/loki-logger-ts": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/loki-logger-ts/-/loki-logger-ts-1.0.2.tgz", + "integrity": "sha512-SV/B5o+9jaxiThcU5N3LUxCNTx20IgR9xjCjx/ED/pVc/097mqKSRpmvSjvx9ezFcjJlUF7GBkrBBpR6veNp7Q==", + "dependencies": { + "axios": "^1.4.0" + } + }, + "node_modules/long": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", + "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==" + }, + "node_modules/loupe": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "license": "ISC" + }, + "node_modules/lru-memoizer": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz", + "integrity": "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "6.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru-memoizer/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "dev": true, + "license": "ISC" + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "4.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { + "version": "5.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "0.6.4", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/marked": { + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.7.tgz", + "integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mikro-orm": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/mikro-orm/-/mikro-orm-6.4.9.tgz", + "integrity": "sha512-XwVrWNT4NNwS6kHIKFNDfvy8L1eWcBBEHeTVzFFYcnb2ummATaLxqeVkNEmKA68jmdtfQdUmWBqGdbcIPwtL2Q==", + "engines": { + "node": ">= 18.12.0" + } + }, + "node_modules/mime-db": { + "version": "1.53.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "mime-db": "^1.53.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/minizlib": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/mitt": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.8", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.74.0", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "license": "MIT" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/abbrev": { + "version": "1.1.1", + "license": "ISC", + "optional": true + }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "optional": true, + "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/node-gyp/node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "5.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "dev": true, + "license": "MIT" + }, + "node_modules/nopt": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^3.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-all2": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.6", + "memorystream": "^0.3.1", + "minimatch": "^9.0.0", + "pidtree": "^0.6.0", + "read-package-json-fast": "^4.0.0", + "shell-quote": "^1.7.3", + "which": "^5.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0", + "npm": ">= 9" + } + }, + "node_modules/npm-run-all2/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm-run-all2/node_modules/isexe": { + "version": "3.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm-run-all2/node_modules/which": { + "version": "5.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.16", + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/oidc-client-ts": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.2.0.tgz", + "integrity": "sha512-wUvVcG3SXzZDKHxi/VGQGaTUk9qguMKfYh26Y1zOVrQsu1zp85JWx/SjZzKSXK5j3NA1RcasgMoaHe6gt1WNtw==", + "dependencies": { + "jwt-decode": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/open": { + "version": "10.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-require": { + "version": "1.0.0", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.2.1", + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==", + "bin": { + "pegjs": "bin/pegjs" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pg": { + "version": "8.13.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.3.tgz", + "integrity": "sha512-P6tPt9jXbL9HVu/SSRERNYaYG++MjnscnegFh9pPHihfoBSujsrka0hyuymMzeJKFWrcG8wvCKy8rCe8e5nDUQ==", + "dependencies": { + "pg-connection-string": "^2.7.0", + "pg-pool": "^3.7.1", + "pg-protocol": "^1.7.1", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.8.0.tgz", + "integrity": "sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.8.0.tgz", + "integrity": "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg-types/node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/pg-types/node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pg-types/node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pg/node_modules/pg-connection-string": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", + "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==" + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/playwright": { + "version": "1.50.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.50.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.50.1", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-array": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz", + "integrity": "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-interval": { + "version": "4.0.2", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.5.1", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-ms": { + "version": "9.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "dev": true, + "license": "ISC" + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "4.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "license": "Apache-2.0" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/response-time": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.3.tgz", + "integrity": "sha512-SsjjOPHl/FfrTQNgmc5oen8Hr1Jxpn6LlHNXxCIFdYMHuK1kMeYMobb9XN3mvxaGQm3dbegqYFMX4+GDORfbWg==", + "dependencies": { + "depd": "~2.0.0", + "on-headers": "~1.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "optional": true, + "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/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/rollup": { + "version": "4.34.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.34.8", + "@rollup/rollup-android-arm64": "4.34.8", + "@rollup/rollup-darwin-arm64": "4.34.8", + "@rollup/rollup-darwin-x64": "4.34.8", + "@rollup/rollup-freebsd-arm64": "4.34.8", + "@rollup/rollup-freebsd-x64": "4.34.8", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", + "@rollup/rollup-linux-arm-musleabihf": "4.34.8", + "@rollup/rollup-linux-arm64-gnu": "4.34.8", + "@rollup/rollup-linux-arm64-musl": "4.34.8", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", + "@rollup/rollup-linux-riscv64-gnu": "4.34.8", + "@rollup/rollup-linux-s390x-gnu": "4.34.8", + "@rollup/rollup-linux-x64-gnu": "4.34.8", + "@rollup/rollup-linux-x64-musl": "4.34.8", + "@rollup/rollup-win32-arm64-msvc": "4.34.8", + "@rollup/rollup-win32-ia32-msvc": "4.34.8", + "@rollup/rollup-win32-x64-msvc": "4.34.8", + "fsevents": "~2.3.2" + } + }, + "node_modules/router": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "license": "MIT" + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "7.7.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "destroy": "^1.2.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "http-errors": "^2.0.0", + "mime-types": "^2.1.35", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/send/node_modules/fresh": { + "version": "0.5.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/sirv": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snappy": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/snappy/-/snappy-7.2.2.tgz", + "integrity": "sha512-iADMq1kY0v3vJmGTuKcFWSXt15qYUz7wFkArOrsSg0IFfI3nJqIJvK2/ZbEIndg7erIJLtAVX2nSOqPz7DcwbA==", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/snappy-android-arm-eabi": "7.2.2", + "@napi-rs/snappy-android-arm64": "7.2.2", + "@napi-rs/snappy-darwin-arm64": "7.2.2", + "@napi-rs/snappy-darwin-x64": "7.2.2", + "@napi-rs/snappy-freebsd-x64": "7.2.2", + "@napi-rs/snappy-linux-arm-gnueabihf": "7.2.2", + "@napi-rs/snappy-linux-arm64-gnu": "7.2.2", + "@napi-rs/snappy-linux-arm64-musl": "7.2.2", + "@napi-rs/snappy-linux-x64-gnu": "7.2.2", + "@napi-rs/snappy-linux-x64-musl": "7.2.2", + "@napi-rs/snappy-win32-arm64-msvc": "7.2.2", + "@napi-rs/snappy-win32-ia32-msvc": "7.2.2", + "@napi-rs/snappy-win32-x64-msvc": "7.2.2" + } + }, + "node_modules/socks": { + "version": "2.8.4", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/sqlstring-sqlite": { + "version": "0.1.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ssri/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.8.0", + "dev": true, + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/superjson": { + "version": "2.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "dev": true + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "license": "MIT" + }, + "node_modules/synckit": { + "version": "0.9.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/tarn": { + "version": "3.0.2", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, + "node_modules/tildify": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.77", + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.77" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.77", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie": { + "version": "5.1.1", + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-morph": { + "version": "25.0.1", + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.26.0", + "code-block-writer": "^13.0.3" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.19.3", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.7.3", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.24.1", + "@typescript-eslint/parser": "8.24.1", + "@typescript-eslint/utils": "8.24.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.2", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-polyfill": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.13.tgz", + "integrity": "sha512-tXzkojrv2SujumYthZ/WjF7jaSfNhSXlYMpE5AYdL2I3D7DCeo+mch8KtW2rUuKjDg+3VXODXHVgipt8yGY/eQ==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "11.1.0", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "6.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.24.2", + "postcss": "^8.5.2", + "rollup": "^4.30.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-hot-client": { + "version": "0.2.4", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0" + } + }, + "node_modules/vite-node": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-plugin-inspect": { + "version": "0.8.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@antfu/utils": "^0.7.10", + "@rollup/pluginutils": "^5.1.3", + "debug": "^4.3.7", + "error-stack-parser-es": "^0.1.5", + "fs-extra": "^11.2.0", + "open": "^10.1.0", + "perfect-debounce": "^1.0.0", + "picocolors": "^1.1.1", + "sirv": "^3.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "7.7.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-core": "^7.7.2", + "@vue/devtools-kit": "^7.7.2", + "@vue/devtools-shared": "^7.7.2", + "execa": "^9.5.1", + "sirv": "^3.0.0", + "vite-plugin-inspect": "0.8.9", + "vite-plugin-vue-inspector": "^5.3.1" + }, + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "vite": "^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0" + } + }, + "node_modules/vite-plugin-vue-inspector": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" + }, + "peerDependencies": { + "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.24.2", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.24.2", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + }, + "node_modules/vitest": { + "version": "3.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "3.0.6", + "@vitest/mocker": "3.0.6", + "@vitest/pretty-format": "^3.0.6", + "@vitest/runner": "3.0.6", + "@vitest/snapshot": "3.0.6", + "@vitest/spy": "3.0.6", + "@vitest/utils": "3.0.6", + "chai": "^5.2.0", + "debug": "^4.4.0", + "expect-type": "^1.1.0", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.0.6", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.0.6", + "@vitest/ui": "3.0.6", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.13", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-sfc": "3.5.13", + "@vue/runtime-dom": "3.5.13", + "@vue/server-renderer": "3.5.13", + "@vue/shared": "3.5.13" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-component-type-helpers": { + "version": "2.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "7.2.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/vue-eslint-parser/node_modules/espree": { + "version": "9.6.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/vue-router": { + "version": "4.5.0", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "2.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "~2.4.11", + "@vue/language-core": "2.2.2" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/vuetify": { + "version": "3.7.12", + "license": "MIT", + "engines": { + "node": "^12.20 || >=14.13" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=1.0.0", + "vue": "^3.3.0", + "webpack-plugin-vuetify": ">=2.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/w3c-xmlserializer/node_modules/xml-name-validator": { + "version": "5.0.0", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.1.1", + "license": "MIT", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT", + "optional": true + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/winston": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", + "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-loki": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/winston-loki/-/winston-loki-6.1.3.tgz", + "integrity": "sha512-DjWtJ230xHyYQWr9mZJa93yhwHttn3JEtSYWP8vXZWJOahiQheUhf+88dSIidbGXB3u0oLweV6G1vkL/ouT62Q==", + "dependencies": { + "async-exit-hook": "2.0.1", + "btoa": "^1.2.1", + "protobufjs": "^7.2.4", + "url-polyfill": "^1.1.12", + "winston-transport": "^4.3.0" + }, + "optionalDependencies": { + "snappy": "^7.2.2" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.0", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "license": "MIT" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} From e78849f5683f3c2edda03ff1d26f091d7ca600b7 Mon Sep 17 00:00:00 2001 From: Lint Action Date: Thu, 13 Mar 2025 17:45:28 +0000 Subject: [PATCH 40/49] style: fix linting issues met ESLint --- backend/src/controllers/groups.ts | 2 +- backend/src/controllers/questions.ts | 30 +++++++++---------- backend/src/controllers/submissions.ts | 16 +++++----- .../src/data/questions/question-repository.ts | 6 ++-- backend/src/data/users/student-repository.ts | 4 +-- .../entities/assignments/assignment.entity.ts | 16 +++------- .../src/entities/assignments/group.entity.ts | 4 +-- .../classes/class-join-request.entity.ts | 4 +-- backend/src/entities/classes/class.entity.ts | 4 +-- .../src/entities/content/attachment.entity.ts | 8 ++--- backend/src/interfaces/class.ts | 8 ++--- backend/src/interfaces/group.ts | 4 +-- backend/src/interfaces/submission.ts | 6 ++-- backend/src/routes/questions.ts | 2 +- backend/src/services/class.ts | 10 ++----- backend/src/services/learning-objects.ts | 16 +++------- backend/src/services/questions.ts | 10 +++---- backend/src/services/students.ts | 8 ++--- backend/src/services/submissions.ts | 2 +- backend/src/services/teachers.ts | 16 +++------- backend/src/services/users.ts | 4 +-- 21 files changed, 64 insertions(+), 116 deletions(-) diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 5fd90553..9ef5b93c 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -83,7 +83,7 @@ export async function getGroupSubmissionsHandler( res: Response, ): Promise { const classId = req.params.classid; - // const full = req.query.full === 'true'; + // Const full = req.query.full === 'true'; const assignmentId = +req.params.assignmentid; diff --git a/backend/src/controllers/questions.ts b/backend/src/controllers/questions.ts index 2b57f4c9..b4451aa2 100644 --- a/backend/src/controllers/questions.ts +++ b/backend/src/controllers/questions.ts @@ -32,7 +32,7 @@ function getQuestionId(req: Request, res: Response): QuestionId | null { const learningObjectIdentifier = getObjectId(req,res); if (!learningObjectIdentifier) - return null + {return null} return { learningObjectIdentifier, @@ -48,28 +48,28 @@ export async function getAllQuestionsHandler( const full = req.query.full === 'true'; if (!objectId) - return + {return} const questions = await getAllQuestions(objectId, full); if (!questions) - res.status(404).json({ error: `Questions not found.` }); + {res.status(404).json({ error: `Questions not found.` });} else - res.json(questions); + {res.json(questions);} } export async function getQuestionHandler(req: Request, res: Response): Promise { const questionId = getQuestionId(req, res); if (!questionId) - return + {return} const question = await getQuestion(questionId); if (!question) - res.status(404).json({ error: `Question not found.` }); + {res.status(404).json({ error: `Question not found.` });} else - res.json(question) + {res.json(question)} } export async function getQuestionAnswersHandler(req: Request, res: Response): Promise { @@ -77,14 +77,14 @@ export async function getQuestionAnswersHandler(req: Request, res: Response): Pr const full = req.query.full === 'true'; if (!questionId) - return + {return} const answers = getAnswersByQuestion(questionId, full); if (!answers) - res.status(404).json({ error: `Questions not found.` }); + {res.status(404).json({ error: `Questions not found.` });} else - res.json(answers) + {res.json(answers)} } export async function createQuestionHandler(req: Request, res: Response): Promise { @@ -98,23 +98,23 @@ export async function createQuestionHandler(req: Request, res: Response): Promis const question = await createQuestion(questionDTO); if (!question) - res.status(400).json({error: 'Could not add question'}); + {res.status(400).json({error: 'Could not add question'});} else - res.json(question) + {res.json(question)} } export async function deleteQuestionHandler(req: Request, res: Response): Promise { const questionId = getQuestionId(req, res); if (!questionId) - return + {return} const question = await deleteQuestion(questionId); if (!question) - res.status(400).json({error: 'Could not find nor delete question'}); + {res.status(400).json({error: 'Could not find nor delete question'});} else - res.json(question) + {res.json(question)} } diff --git a/backend/src/controllers/submissions.ts b/backend/src/controllers/submissions.ts index 4080d1e7..96f0185c 100644 --- a/backend/src/controllers/submissions.ts +++ b/backend/src/controllers/submissions.ts @@ -20,8 +20,8 @@ export async function getSubmissionHandler( return; } - let lang = languageMap[req.query.language as string] || Language.Dutch; - let version = (req.query.version || 1) as number; + const lang = languageMap[req.query.language as string] || Language.Dutch; + const version = (req.query.version || 1) as number; const submission = await getSubmission(lohruid, lang, version, submissionNumber); @@ -39,22 +39,22 @@ export async function createSubmissionHandler(req: Request, res: Response){ const submission = await createSubmission(submissionDTO); if (!submission) - res.status(404).json({ error: 'Submission not added' }); + {res.status(404).json({ error: 'Submission not added' });} else - res.json(submission) + {res.json(submission)} } export async function deleteSubmissionHandler(req: Request, res: Response){ const hruid = req.params.hruid; const submissionNumber = +req.params.id; - let lang = languageMap[req.query.language as string] || Language.Dutch; - let version = (req.query.version || 1) as number; + const lang = languageMap[req.query.language as string] || Language.Dutch; + const version = (req.query.version || 1) as number; const submission = await deleteSubmission(hruid, lang, version, submissionNumber); if (!submission) - res.status(404).json({ error: 'Submission not found' }); + {res.status(404).json({ error: 'Submission not found' });} else - res.json(submission) + {res.json(submission)} } diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index dc8502d1..e24d48b8 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -50,13 +50,11 @@ export class QuestionRepository extends DwengoEntityRepository { public async findAllByLearningObjects( learningObjects: LearningObject[] ): Promise { - const objectIdentifiers = learningObjects.map((lo) => { - return { + const objectIdentifiers = learningObjects.map((lo) => ({ learningObjectHruid: lo.hruid, learningObjectLanguage: lo.language, learningObjectVersion: lo.version, - }; - }); + })); return this.findAll({ where: { $or: objectIdentifiers }, diff --git a/backend/src/data/users/student-repository.ts b/backend/src/data/users/student-repository.ts index d3be9081..f3cf7b6a 100644 --- a/backend/src/data/users/student-repository.ts +++ b/backend/src/data/users/student-repository.ts @@ -1,9 +1,9 @@ import { Student } from '../../entities/users/student.entity.js'; import { User } from '../../entities/users/user.entity.js'; import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; -// import { UserRepository } from './user-repository.js'; +// Import { UserRepository } from './user-repository.js'; -// export class StudentRepository extends UserRepository {} +// Export class StudentRepository extends UserRepository {} export class StudentRepository extends DwengoEntityRepository { public findByUsername(username: string): Promise { diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index 4992cca4..a1f53386 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -13,15 +13,11 @@ import { Language } from '../content/language.js'; import { AssignmentRepository } from '../../data/assignments/assignment-repository.js'; @Entity({ - repository: () => { - return AssignmentRepository; - }, + repository: () => AssignmentRepository, }) export class Assignment { @ManyToOne({ - entity: () => { - return Class; - }, + entity: () => Class, primary: true, }) within!: Class; @@ -39,16 +35,12 @@ export class Assignment { learningPathHruid!: string; @Enum({ - items: () => { - return Language; - }, + items: () => Language, }) learningPathLanguage!: Language; @OneToMany({ - entity: () => { - return Group; - }, + entity: () => Group, mappedBy: 'assignment', }) groups!: Group[]; diff --git a/backend/src/entities/assignments/group.entity.ts b/backend/src/entities/assignments/group.entity.ts index a961ed53..213e0f38 100644 --- a/backend/src/entities/assignments/group.entity.ts +++ b/backend/src/entities/assignments/group.entity.ts @@ -4,9 +4,7 @@ import { Student } from '../users/student.entity.js'; import { GroupRepository } from '../../data/assignments/group-repository.js'; @Entity({ - repository: () => { - return GroupRepository; - }, + repository: () => GroupRepository, }) export class Group { @ManyToOne({ diff --git a/backend/src/entities/classes/class-join-request.entity.ts b/backend/src/entities/classes/class-join-request.entity.ts index bf7e6355..bdef1f52 100644 --- a/backend/src/entities/classes/class-join-request.entity.ts +++ b/backend/src/entities/classes/class-join-request.entity.ts @@ -4,9 +4,7 @@ import { Class } from './class.entity.js'; import { ClassJoinRequestRepository } from '../../data/classes/class-join-request-repository.js'; @Entity({ - repository: () => { - return ClassJoinRequestRepository; - }, + repository: () => ClassJoinRequestRepository, }) export class ClassJoinRequest { @ManyToOne({ diff --git a/backend/src/entities/classes/class.entity.ts b/backend/src/entities/classes/class.entity.ts index a2c016ef..a484deff 100644 --- a/backend/src/entities/classes/class.entity.ts +++ b/backend/src/entities/classes/class.entity.ts @@ -11,9 +11,7 @@ import { Student } from '../users/student.entity.js'; import { ClassRepository } from '../../data/classes/class-repository.js'; @Entity({ - repository: () => { - return ClassRepository; - }, + repository: () => ClassRepository, }) export class Class { @PrimaryKey() diff --git a/backend/src/entities/content/attachment.entity.ts b/backend/src/entities/content/attachment.entity.ts index 3903f055..80104f28 100644 --- a/backend/src/entities/content/attachment.entity.ts +++ b/backend/src/entities/content/attachment.entity.ts @@ -3,15 +3,11 @@ import { LearningObject } from './learning-object.entity.js'; import { AttachmentRepository } from '../../data/content/attachment-repository.js'; @Entity({ - repository: () => { - return AttachmentRepository; - }, + repository: () => AttachmentRepository, }) export class Attachment { @ManyToOne({ - entity: () => { - return LearningObject; - }, + entity: () => LearningObject, primary: true, }) learningObject!: LearningObject; diff --git a/backend/src/interfaces/class.ts b/backend/src/interfaces/class.ts index 379a8635..e04ce2d4 100644 --- a/backend/src/interfaces/class.ts +++ b/backend/src/interfaces/class.ts @@ -21,12 +21,8 @@ export function mapToClassDTO(cls: Class): ClassDTO { return { id: cls.classId!, displayName: cls.displayName, - teachers: cls.teachers.map((teacher) => { - return teacher.username; - }), - students: cls.students.map((student) => { - return student.username; - }), + teachers: cls.teachers.map((teacher) => teacher.username), + students: cls.students.map((student) => student.username), joinRequests: [], // TODO }; } diff --git a/backend/src/interfaces/group.ts b/backend/src/interfaces/group.ts index 2dd3f2c1..a25c5b8e 100644 --- a/backend/src/interfaces/group.ts +++ b/backend/src/interfaces/group.ts @@ -20,8 +20,6 @@ export function mapToGroupDTOId(group: Group): GroupDTO { return { assignment: group.assignment.id!, groupNumber: group.groupNumber!, - members: group.members.map((member) => { - return member.username; - }), + members: group.members.map((member) => member.username), }; } diff --git a/backend/src/interfaces/submission.ts b/backend/src/interfaces/submission.ts index 2400075f..40b76fad 100644 --- a/backend/src/interfaces/submission.ts +++ b/backend/src/interfaces/submission.ts @@ -36,10 +36,10 @@ export function mapToSubmission(submissionDTO: SubmissionDTO): Submission { submission.learningObjectHruid = submissionDTO.learningObjectHruid; submission.learningObjectLanguage = submissionDTO.learningObjectLanguage; submission.learningObjectVersion = submissionDTO.learningObjectVersion; - // submission.submissionNumber = submissionDTO.submissionNumber; + // Submission.submissionNumber = submissionDTO.submissionNumber; submission.submitter = mapToStudent(submissionDTO.submitter) ; - // submission.submissionTime = submissionDTO.time; - // submission.onBehalfOf = submissionDTO.group!; + // Submission.submissionTime = submissionDTO.time; + // Submission.onBehalfOf = submissionDTO.group!; // TODO fix group submission.content = submissionDTO.content; diff --git a/backend/src/routes/questions.ts b/backend/src/routes/questions.ts index d635a85e..d9a4dd9d 100644 --- a/backend/src/routes/questions.ts +++ b/backend/src/routes/questions.ts @@ -7,7 +7,7 @@ import { } from "../controllers/questions.js"; const router = express.Router({ mergeParams: true }); -// query language +// Query language // Root endpoint used to search objects router.get('/', getAllQuestionsHandler); diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index a7f5f7ea..4b76d0cd 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -29,9 +29,7 @@ export async function getAllClasses( if (full) { return classes.map(mapToClassDTO); } - return classes.map((cls) => { - return cls.classId!; - }); + return classes.map((cls) => cls.classId!); } export async function createClass(classData: ClassDTO): Promise { @@ -45,7 +43,7 @@ export async function createClass(classData: ClassDTO): Promise { const students = (await Promise.all(studentUsernames.map(id => studentRepository.findByUsername(id)))) .filter(student => student != null); - //const cls = mapToClass(classData, teachers, students); + //Const cls = mapToClass(classData, teachers, students); const classRepository = getClassRepository(); @@ -91,9 +89,7 @@ export async function getClassStudents(classId: string): Promise { export async function getClassStudentsIds(classId: string): Promise { const students: StudentDTO[] = await fetchClassStudents(classId); - return students.map((student) => { - return student.username; - }); + return students.map((student) => student.username); } export async function getClassTeacherInvitations( diff --git a/backend/src/services/learning-objects.ts b/backend/src/services/learning-objects.ts index 4f7d66a8..dfde4da7 100644 --- a/backend/src/services/learning-objects.ts +++ b/backend/src/services/learning-objects.ts @@ -85,23 +85,15 @@ async function fetchLearningObjects( const nodes: LearningObjectNode[] = learningPathResponse.data[0].nodes; if (!full) { - return nodes.map((node) => { - return node.learningobject_hruid; - }); + return nodes.map((node) => node.learningobject_hruid); } return await Promise.all( - nodes.map(async (node) => { - return getLearningObjectById( + nodes.map(async (node) => getLearningObjectById( node.learningobject_hruid, language - ); - }) - ).then((objects) => { - return objects.filter((obj): obj is FilteredLearningObject => { - return obj !== null; - }); - }); + )) + ).then((objects) => objects.filter((obj): obj is FilteredLearningObject => obj !== null)); } catch (error) { console.error('❌ Error fetching learning objects:', error); return []; diff --git a/backend/src/services/questions.ts b/backend/src/services/questions.ts index 6be684f9..238ebd45 100644 --- a/backend/src/services/questions.ts +++ b/backend/src/services/questions.ts @@ -45,7 +45,7 @@ export async function getQuestion(questionId: QuestionId): Promise { export async function getAllStudentIds(): Promise { const users = await getAllStudents(); - return users.map((user) => { - return user.username; - }); + return users.map((user) => user.username); } export async function getStudent(username: string): Promise { @@ -98,9 +96,7 @@ export async function getStudentAssignments(username: string, full: boolean): Pr const assignments = ( await Promise.all( - classes.map(async (cls) => { - return await getAllAssignments(cls.classId!, full); - }) + classes.map(async (cls) => await getAllAssignments(cls.classId!, full)) ) ).flat(); diff --git a/backend/src/services/submissions.ts b/backend/src/services/submissions.ts index ce6f7bff..c9135001 100644 --- a/backend/src/services/submissions.ts +++ b/backend/src/services/submissions.ts @@ -46,7 +46,7 @@ export async function deleteSubmission( const submission = getSubmission(learningObjectHruid, language, version, submissionNumber); if (!submission) - return null + {return null} const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(loId, submissionNumber); diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 12325857..2f462ed9 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -27,9 +27,7 @@ export async function getAllTeachers(): Promise { export async function getAllTeacherIds(): Promise { const users = await getAllTeachers(); - return users.map((user) => { - return user.username; - }); + return users.map((user) => user.username); } export async function getTeacher(username: string): Promise { @@ -89,9 +87,7 @@ export async function getClassesByTeacher(username: string): Promise export async function getClassIdsByTeacher(username: string): Promise { const classes = await fetchClassesByTeacher(username); - return classes.map((cls) => { - return cls.id; - }); + return classes.map((cls) => cls.id); } export async function fetchStudentsByTeacher(username: string) { @@ -99,9 +95,7 @@ export async function fetchStudentsByTeacher(username: string) { return ( await Promise.all( - classes.map(async (id) => { - return getClassStudents(id); - }) + classes.map(async (id) => getClassStudents(id)) ) ).flat(); } @@ -112,9 +106,7 @@ export async function getStudentsByTeacher(username: string): Promise { const students = await fetchStudentsByTeacher(username); - return students.map((student) => { - return student.username; - }); + return students.map((student) => student.username); } export async function fetchTeacherQuestions(username: string): Promise { diff --git a/backend/src/services/users.ts b/backend/src/services/users.ts index fc1ea599..65ed5d4c 100644 --- a/backend/src/services/users.ts +++ b/backend/src/services/users.ts @@ -16,9 +16,7 @@ export class UserService { async getAllUserIds(): Promise { const users = await this.getAllUsers(); - return users.map((user) => { - return user.username; - }); + return users.map((user) => user.username); } async getUserByUsername(username: string): Promise { From 400a955850e66dd5bbf00af548a40fb8c150e785 Mon Sep 17 00:00:00 2001 From: Lint Action Date: Thu, 13 Mar 2025 17:45:32 +0000 Subject: [PATCH 41/49] style: fix linting issues met Prettier --- backend/src/config.ts | 2 +- backend/src/controllers/assignments.ts | 28 +--- backend/src/controllers/classes.ts | 42 ++---- backend/src/controllers/groups.ts | 26 +--- backend/src/controllers/questions.ts | 120 +++++++++--------- backend/src/controllers/students.ts | 52 ++------ backend/src/controllers/submissions.ts | 37 +++--- backend/src/controllers/teachers.ts | 66 ++++------ backend/src/controllers/users.ts | 29 +---- .../src/data/assignments/group-repository.ts | 23 +--- .../data/assignments/submission-repository.ts | 36 ++---- backend/src/data/classes/class-repository.ts | 10 +- .../src/data/questions/answer-repository.ts | 5 +- .../src/data/questions/question-repository.ts | 21 +-- backend/src/data/repositories.ts | 4 +- backend/src/data/users/student-repository.ts | 2 +- backend/src/data/users/teacher-repository.ts | 2 +- .../entities/assignments/assignment.entity.ts | 10 +- backend/src/entities/classes/class.entity.ts | 8 +- backend/src/entities/content/language.ts | 2 +- .../content/learning-object.entity.ts | 11 +- backend/src/interfaces/answer.ts | 10 +- backend/src/interfaces/class.ts | 8 +- backend/src/interfaces/question.ts | 9 +- backend/src/interfaces/student.ts | 6 +- backend/src/interfaces/submission.ts | 32 ++--- backend/src/interfaces/teacher-invitation.ts | 8 +- backend/src/interfaces/teacher.ts | 6 +- backend/src/interfaces/user.ts | 5 +- backend/src/routes/learning-objects.ts | 10 +- backend/src/routes/questions.ts | 7 +- backend/src/routes/submissions.ts | 4 +- backend/src/services/assignments.ts | 47 ++----- backend/src/services/class.ts | 38 ++---- backend/src/services/groups.ts | 63 ++------- backend/src/services/learning-objects.ts | 65 ++-------- backend/src/services/questions.ts | 87 ++++++------- backend/src/services/students.ts | 28 ++-- backend/src/services/submissions.ts | 26 ++-- backend/src/services/teachers.ts | 26 +--- 40 files changed, 321 insertions(+), 700 deletions(-) diff --git a/backend/src/config.ts b/backend/src/config.ts index 65582c8b..69af5d74 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -1,5 +1,5 @@ import { EnvVars, getEnvVar } from './util/envvars.js'; -import {Language} from "./entities/content/language.js"; +import { Language } from './entities/content/language.js'; // API export const DWENGO_API_BASE = getEnvVar(EnvVars.LearningContentRepoApiBaseUrl); diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index dcaa07a2..b0695b85 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -9,10 +9,7 @@ interface AssignmentParams { id: string; } -export async function getAllAssignmentsHandler( - req: Request, - res: Response -): Promise { +export async function getAllAssignmentsHandler(req: Request, res: Response): Promise { const classid = req.params.classid; const full = req.query.full === 'true'; @@ -23,18 +20,11 @@ export async function getAllAssignmentsHandler( }); } -export async function createAssignmentHandler( - req: Request, - res: Response, -): Promise { +export async function createAssignmentHandler(req: Request, res: Response): Promise { const classid = req.params.classid; const assignmentData = req.body as AssignmentDTO; - if (!assignmentData.description - || !assignmentData.language - || !assignmentData.learningPath - || !assignmentData.title - ) { + if (!assignmentData.description || !assignmentData.language || !assignmentData.learningPath || !assignmentData.title) { res.status(400).json({ error: 'Missing one or more required fields: title, description, learningPath, title', }); @@ -44,17 +34,14 @@ export async function createAssignmentHandler( const assignment = createAssignment(classid, assignmentData); if (!assignment) { - res.status(500).json({ error: "Could not create assignment "}); + res.status(500).json({ error: 'Could not create assignment ' }); return; } res.status(201).json({ assignment: assignment }); } -export async function getAssignmentHandler( - req: Request, - res: Response -): Promise { +export async function getAssignmentHandler(req: Request, res: Response): Promise { const id = +req.params.id; const classid = req.params.classid; @@ -73,10 +60,7 @@ export async function getAssignmentHandler( res.json(assignment); } -export async function getAssignmentsSubmissionsHandler( - req: Request, - res: Response, -): Promise { +export async function getAssignmentsSubmissionsHandler(req: Request, res: Response): Promise { const classid = req.params.classid; const assignmentNumber = +req.params.id; diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index 5fd4ce9d..6fb58fb9 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,19 +1,9 @@ import { Request, Response } from 'express'; -import { - createClass, - getAllClasses, - getClass, - getClassStudents, - getClassStudentsIds, - getClassTeacherInvitations, -} from '../services/class.js'; +import { createClass, getAllClasses, getClass, getClassStudents, getClassStudentsIds, getClassTeacherInvitations } from '../services/class.js'; import { ClassDTO, mapToClass } from '../interfaces/class.js'; import { getClassRepository, getStudentRepository, getTeacherRepository } from '../data/repositories.js'; -export async function getAllClassesHandler( - req: Request, - res: Response -): Promise { +export async function getAllClassesHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; const classes = await getAllClasses(full); @@ -22,10 +12,7 @@ export async function getAllClassesHandler( }); } -export async function createClassHandler( - req: Request, - res: Response, -): Promise { +export async function createClassHandler(req: Request, res: Response): Promise { const classData = req.body as ClassDTO; if (!classData.displayName) { @@ -38,17 +25,14 @@ export async function createClassHandler( const cls = await createClass(classData); if (!cls) { - res.status(500).json({ error: "Something went wrong while creating class" }); - return + res.status(500).json({ error: 'Something went wrong while creating class' }); + return; } res.status(201).json({ class: cls }); } -export async function getClassHandler( - req: Request, - res: Response -): Promise { +export async function getClassHandler(req: Request, res: Response): Promise { try { const classId = req.params.id; const cls = await getClass(classId); @@ -71,26 +55,18 @@ export async function getClassHandler( } } -export async function getClassStudentsHandler( - req: Request, - res: Response -): Promise { +export async function getClassStudentsHandler(req: Request, res: Response): Promise { const classId = req.params.id; const full = req.query.full === 'true'; - const students = full - ? await getClassStudents(classId) - : await getClassStudentsIds(classId); + const students = full ? await getClassStudents(classId) : await getClassStudentsIds(classId); res.json({ students: students, }); } -export async function getTeacherInvitationsHandler( - req: Request, - res: Response -): Promise { +export async function getTeacherInvitationsHandler(req: Request, res: Response): Promise { const classId = req.params.id; const full = req.query.full === 'true'; // TODO: not implemented yet diff --git a/backend/src/controllers/groups.ts b/backend/src/controllers/groups.ts index 9ef5b93c..dbe83060 100644 --- a/backend/src/controllers/groups.ts +++ b/backend/src/controllers/groups.ts @@ -9,10 +9,7 @@ interface GroupParams { groupid?: string; } -export async function getGroupHandler( - req: Request, - res: Response -): Promise { +export async function getGroupHandler(req: Request, res: Response): Promise { const classId = req.params.classid; const full = req.query.full === 'true'; const assignmentId = +req.params.assignmentid; @@ -34,10 +31,7 @@ export async function getGroupHandler( res.json(group); } -export async function getAllGroupsHandler( - req: Request, - res: Response -): Promise { +export async function getAllGroupsHandler(req: Request, res: Response): Promise { const classId = req.params.classid; const full = req.query.full === 'true'; @@ -55,10 +49,7 @@ export async function getAllGroupsHandler( }); } -export async function createGroupHandler( - req: Request, - res: Response, -): Promise { +export async function createGroupHandler(req: Request, res: Response): Promise { const classid = req.params.classid; const assignmentId = +req.params.assignmentid; @@ -71,17 +62,14 @@ export async function createGroupHandler( const group = createGroup(groupData, classid, assignmentId); if (!group) { - res.status(500).json({ error: "Something went wrong while creating group" }); - return + res.status(500).json({ error: 'Something went wrong while creating group' }); + return; } res.status(201).json({ group: group }); } -export async function getGroupSubmissionsHandler( - req: Request, - res: Response, -): Promise { +export async function getGroupSubmissionsHandler(req: Request, res: Response): Promise { const classId = req.params.classid; // Const full = req.query.full === 'true'; @@ -104,4 +92,4 @@ export async function getGroupSubmissionsHandler( res.json({ submissions: submissions, }); -} \ No newline at end of file +} diff --git a/backend/src/controllers/questions.ts b/backend/src/controllers/questions.ts index b4451aa2..917b48ae 100644 --- a/backend/src/controllers/questions.ts +++ b/backend/src/controllers/questions.ts @@ -1,121 +1,119 @@ -import {Request, Response} from "express"; -import { - createQuestion, - deleteQuestion, - getAllQuestions, - getAnswersByQuestion, - getQuestion -} from "../services/questions.js"; -import {QuestionDTO, QuestionId} from "../interfaces/question.js"; -import {FALLBACK_LANG, FALLBACK_SEQ_NUM} from "../config.js"; -import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; -import {Language} from "../entities/content/language.js"; +import { Request, Response } from 'express'; +import { createQuestion, deleteQuestion, getAllQuestions, getAnswersByQuestion, getQuestion } from '../services/questions.js'; +import { QuestionDTO, QuestionId } from '../interfaces/question.js'; +import { FALLBACK_LANG, FALLBACK_SEQ_NUM } from '../config.js'; +import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; +import { Language } from '../entities/content/language.js'; function getObjectId(req: Request, res: Response): LearningObjectIdentifier | null { - const { hruid, version } = req.params - const lang = req.query.lang + const { hruid, version } = req.params; + const lang = req.query.lang; - if (!hruid || !version ) { - res.status(400).json({ error: "Missing required parameters." }); + if (!hruid || !version) { + res.status(400).json({ error: 'Missing required parameters.' }); return null; } return { hruid, - language: lang as Language || FALLBACK_LANG, - version: +version - } + language: (lang as Language) || FALLBACK_LANG, + version: +version, + }; } function getQuestionId(req: Request, res: Response): QuestionId | null { - const seq = req.params.seq - const learningObjectIdentifier = getObjectId(req,res); + const seq = req.params.seq; + const learningObjectIdentifier = getObjectId(req, res); - if (!learningObjectIdentifier) - {return null} + if (!learningObjectIdentifier) { + return null; + } return { learningObjectIdentifier, - sequenceNumber: seq ? Number(seq) : FALLBACK_SEQ_NUM - } + sequenceNumber: seq ? Number(seq) : FALLBACK_SEQ_NUM, + }; } -export async function getAllQuestionsHandler( - req: Request, - res: Response -): Promise { +export async function getAllQuestionsHandler(req: Request, res: Response): Promise { const objectId = getObjectId(req, res); const full = req.query.full === 'true'; - if (!objectId) - {return} + if (!objectId) { + return; + } const questions = await getAllQuestions(objectId, full); - if (!questions) - {res.status(404).json({ error: `Questions not found.` });} - else - {res.json(questions);} + if (!questions) { + res.status(404).json({ error: `Questions not found.` }); + } else { + res.json(questions); + } } export async function getQuestionHandler(req: Request, res: Response): Promise { const questionId = getQuestionId(req, res); - if (!questionId) - {return} + if (!questionId) { + return; + } const question = await getQuestion(questionId); - if (!question) - {res.status(404).json({ error: `Question not found.` });} - else - {res.json(question)} + if (!question) { + res.status(404).json({ error: `Question not found.` }); + } else { + res.json(question); + } } export async function getQuestionAnswersHandler(req: Request, res: Response): Promise { const questionId = getQuestionId(req, res); const full = req.query.full === 'true'; - if (!questionId) - {return} + if (!questionId) { + return; + } const answers = getAnswersByQuestion(questionId, full); - if (!answers) - {res.status(404).json({ error: `Questions not found.` });} - else - {res.json(answers)} + if (!answers) { + res.status(404).json({ error: `Questions not found.` }); + } else { + res.json(answers); + } } export async function createQuestionHandler(req: Request, res: Response): Promise { const questionDTO = req.body as QuestionDTO; if (!questionDTO.learningObjectIdentifier || !questionDTO.author || !questionDTO.content) { - res.status(400).json({error: 'Missing required fields: identifier and content'}); + res.status(400).json({ error: 'Missing required fields: identifier and content' }); return; } const question = await createQuestion(questionDTO); - if (!question) - {res.status(400).json({error: 'Could not add question'});} - else - {res.json(question)} + if (!question) { + res.status(400).json({ error: 'Could not add question' }); + } else { + res.json(question); + } } export async function deleteQuestionHandler(req: Request, res: Response): Promise { const questionId = getQuestionId(req, res); - if (!questionId) - {return} + if (!questionId) { + return; + } const question = await deleteQuestion(questionId); - if (!question) - {res.status(400).json({error: 'Could not find nor delete question'});} - else - {res.json(question)} + if (!question) { + res.status(400).json({ error: 'Could not find nor delete question' }); + } else { + res.json(question); + } } - - - diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index aae37b50..5c17513d 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -10,9 +10,7 @@ import { } from '../services/students.js'; import { ClassDTO } from '../interfaces/class.js'; import { getAllAssignments } from '../services/assignments.js'; -import { - getUserHandler, -} from './users.js'; +import { getUserHandler } from './users.js'; import { Student } from '../entities/users/student.entity.js'; import { StudentDTO } from '../interfaces/student.js'; import { getStudentRepository } from '../data/repositories.js'; @@ -20,17 +18,12 @@ import { UserDTO } from '../interfaces/user.js'; // TODO: accept arguments (full, ...) // TODO: endpoints -export async function getAllStudentsHandler( - req: Request, - res: Response, -): Promise { +export async function getAllStudentsHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; const studentRepository = getStudentRepository(); - const students: StudentDTO[] | string[] = full - ? await getAllStudents() - : await getAllStudents(); + const students: StudentDTO[] | string[] = full ? await getAllStudents() : await getAllStudents(); if (!students) { res.status(404).json({ error: `Student not found.` }); @@ -40,11 +33,7 @@ export async function getAllStudentsHandler( res.status(201).json(students); } - -export async function getStudentHandler( - req: Request, - res: Response, -): Promise { +export async function getStudentHandler(req: Request, res: Response): Promise { const username = req.params.username; if (!username) { @@ -64,10 +53,7 @@ export async function getStudentHandler( res.status(201).json(user); } -export async function createStudentHandler( - req: Request, - res: Response, -) { +export async function createStudentHandler(req: Request, res: Response) { const userData = req.body as StudentDTO; if (!userData.username || !userData.firstName || !userData.lastName) { @@ -81,10 +67,7 @@ export async function createStudentHandler( res.status(201).json(newUser); } -export async function deleteStudentHandler( - req: Request, - res: Response, -) { +export async function deleteStudentHandler(req: Request, res: Response) { const username = req.params.username; if (!username) { @@ -103,10 +86,7 @@ export async function deleteStudentHandler( res.status(200).json(deletedUser); } -export async function getStudentClassesHandler( - req: Request, - res: Response -): Promise { +export async function getStudentClassesHandler(req: Request, res: Response): Promise { try { const full = req.query.full === 'true'; const username = req.params.id; @@ -132,10 +112,7 @@ export async function getStudentClassesHandler( // Might not be fully correct depending on if // A class has an assignment, that all students // Have this assignment. -export async function getStudentAssignmentsHandler( - req: Request, - res: Response -): Promise { +export async function getStudentAssignmentsHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; const username = req.params.id; @@ -146,24 +123,18 @@ export async function getStudentAssignmentsHandler( }); } -export async function getStudentGroupsHandler( - req: Request, - res: Response, -): Promise { +export async function getStudentGroupsHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; const username = req.params.id; const groups = await getStudentGroups(username, full); - + res.json({ groups: groups, }); } -export async function getStudentSubmissionsHandler( - req: Request, - res: Response, -): Promise { +export async function getStudentSubmissionsHandler(req: Request, res: Response): Promise { const username = req.params.id; const submissions = await getStudentSubmissions(username); @@ -175,4 +146,3 @@ export async function getStudentSubmissionsHandler( function getAllStudents(): StudentDTO[] | string[] | PromiseLike { throw new Error('Function not implemented.'); } - diff --git a/backend/src/controllers/submissions.ts b/backend/src/controllers/submissions.ts index 96f0185c..1e66dbe9 100644 --- a/backend/src/controllers/submissions.ts +++ b/backend/src/controllers/submissions.ts @@ -1,17 +1,14 @@ -import { Request, Response } from "express"; -import {createSubmission, deleteSubmission, getSubmission} from "../services/submissions.js"; -import { Language, languageMap } from "../entities/content/language.js"; -import {SubmissionDTO} from "../interfaces/submission"; +import { Request, Response } from 'express'; +import { createSubmission, deleteSubmission, getSubmission } from '../services/submissions.js'; +import { Language, languageMap } from '../entities/content/language.js'; +import { SubmissionDTO } from '../interfaces/submission'; interface SubmissionParams { - hruid: string, + hruid: string; id: number; } -export async function getSubmissionHandler( - req: Request, - res: Response, -): Promise { +export async function getSubmissionHandler(req: Request, res: Response): Promise { const lohruid = req.params.hruid; const submissionNumber = +req.params.id; @@ -33,18 +30,19 @@ export async function getSubmissionHandler( res.json(submission); } -export async function createSubmissionHandler(req: Request, res: Response){ +export async function createSubmissionHandler(req: Request, res: Response) { const submissionDTO = req.body as SubmissionDTO; const submission = await createSubmission(submissionDTO); - if (!submission) - {res.status(404).json({ error: 'Submission not added' });} - else - {res.json(submission)} + if (!submission) { + res.status(404).json({ error: 'Submission not added' }); + } else { + res.json(submission); + } } -export async function deleteSubmissionHandler(req: Request, res: Response){ +export async function deleteSubmissionHandler(req: Request, res: Response) { const hruid = req.params.hruid; const submissionNumber = +req.params.id; @@ -53,8 +51,9 @@ export async function deleteSubmissionHandler(req: Request, res: Response){ const submission = await deleteSubmission(hruid, lang, version, submissionNumber); - if (!submission) - {res.status(404).json({ error: 'Submission not found' });} - else - {res.json(submission)} + if (!submission) { + res.status(404).json({ error: 'Submission not found' }); + } else { + res.json(submission); + } } diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index 02846fd9..52e5e713 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -1,5 +1,16 @@ import { Request, Response } from 'express'; -import { createTeacher, deleteTeacher, getAllTeachers, getClassesByTeacher, getClassIdsByTeacher, getQuestionIdsByTeacher, getQuestionsByTeacher, getStudentIdsByTeacher, getStudentsByTeacher, getTeacher } from '../services/teachers.js'; +import { + createTeacher, + deleteTeacher, + getAllTeachers, + getClassesByTeacher, + getClassIdsByTeacher, + getQuestionIdsByTeacher, + getQuestionsByTeacher, + getStudentIdsByTeacher, + getStudentsByTeacher, + getTeacher, +} from '../services/teachers.js'; import { ClassDTO } from '../interfaces/class.js'; import { StudentDTO } from '../interfaces/student.js'; import { QuestionDTO, QuestionId } from '../interfaces/question.js'; @@ -7,17 +18,12 @@ import { Teacher } from '../entities/users/teacher.entity.js'; import { TeacherDTO } from '../interfaces/teacher.js'; import { getTeacherRepository } from '../data/repositories.js'; -export async function getAllTeachersHandler( - req: Request, - res: Response, -): Promise { +export async function getAllTeachersHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; const teacherRepository = getTeacherRepository(); - const teachers: TeacherDTO[] | string[] = full - ? await getAllTeachers() - : await getAllTeachers(); + const teachers: TeacherDTO[] | string[] = full ? await getAllTeachers() : await getAllTeachers(); if (!teachers) { res.status(404).json({ error: `Teacher not found.` }); @@ -27,11 +33,7 @@ export async function getAllTeachersHandler( res.status(201).json(teachers); } - -export async function getTeacherHandler( - req: Request, - res: Response, -): Promise { +export async function getTeacherHandler(req: Request, res: Response): Promise { const username = req.params.username; if (!username) { @@ -51,10 +53,7 @@ export async function getTeacherHandler( res.status(201).json(user); } -export async function createTeacherHandler( - req: Request, - res: Response, -) { +export async function createTeacherHandler(req: Request, res: Response) { const userData = req.body as TeacherDTO; if (!userData.username || !userData.firstName || !userData.lastName) { @@ -68,10 +67,7 @@ export async function createTeacherHandler( res.status(201).json(newUser); } -export async function deleteTeacherHandler( - req: Request, - res: Response, -) { +export async function deleteTeacherHandler(req: Request, res: Response) { const username = req.params.username; if (!username) { @@ -90,11 +86,7 @@ export async function deleteTeacherHandler( res.status(200).json(deletedUser); } - -export async function getTeacherClassHandler( - req: Request, - res: Response -): Promise { +export async function getTeacherClassHandler(req: Request, res: Response): Promise { try { const username = req.params.username as string; const full = req.query.full === 'true'; @@ -104,9 +96,7 @@ export async function getTeacherClassHandler( return; } - const classes: ClassDTO[] | string[] = full - ? await getClassesByTeacher(username) - : await getClassIdsByTeacher(username); + const classes: ClassDTO[] | string[] = full ? await getClassesByTeacher(username) : await getClassIdsByTeacher(username); res.status(201).json(classes); } catch (error) { @@ -115,10 +105,7 @@ export async function getTeacherClassHandler( } } -export async function getTeacherStudentHandler( - req: Request, - res: Response -): Promise { +export async function getTeacherStudentHandler(req: Request, res: Response): Promise { try { const username = req.params.username as string; const full = req.query.full === 'true'; @@ -128,9 +115,7 @@ export async function getTeacherStudentHandler( return; } - const students: StudentDTO[] | string[] = full - ? await getStudentsByTeacher(username) - : await getStudentIdsByTeacher(username); + const students: StudentDTO[] | string[] = full ? await getStudentsByTeacher(username) : await getStudentIdsByTeacher(username); res.status(201).json(students); } catch (error) { @@ -139,10 +124,7 @@ export async function getTeacherStudentHandler( } } -export async function getTeacherQuestionHandler( - req: Request, - res: Response -): Promise { +export async function getTeacherQuestionHandler(req: Request, res: Response): Promise { try { const username = req.params.username as string; const full = req.query.full === 'true'; @@ -152,9 +134,7 @@ export async function getTeacherQuestionHandler( return; } - const questions: QuestionDTO[] | QuestionId[] = full - ? await getQuestionsByTeacher(username) - : await getQuestionIdsByTeacher(username); + const questions: QuestionDTO[] | QuestionId[] = full ? await getQuestionsByTeacher(username) : await getQuestionIdsByTeacher(username); res.status(201).json(questions); } catch (error) { diff --git a/backend/src/controllers/users.ts b/backend/src/controllers/users.ts index 8b256a0e..850c6549 100644 --- a/backend/src/controllers/users.ts +++ b/backend/src/controllers/users.ts @@ -3,17 +3,11 @@ import { UserService } from '../services/users.js'; import { UserDTO } from '../interfaces/user.js'; import { User } from '../entities/users/user.entity.js'; -export async function getAllUsersHandler( - req: Request, - res: Response, - service: UserService -): Promise { +export async function getAllUsersHandler(req: Request, res: Response, service: UserService): Promise { try { const full = req.query.full === 'true'; - const users: UserDTO[] | string[] = full - ? await service.getAllUsers() - : await service.getAllUserIds(); + const users: UserDTO[] | string[] = full ? await service.getAllUsers() : await service.getAllUserIds(); if (!users) { res.status(404).json({ error: `Users not found.` }); @@ -27,11 +21,7 @@ export async function getAllUsersHandler( } } -export async function getUserHandler( - req: Request, - res: Response, - service: UserService -): Promise { +export async function getUserHandler(req: Request, res: Response, service: UserService): Promise { try { const username = req.params.username as string; @@ -56,12 +46,7 @@ export async function getUserHandler( } } -export async function createUserHandler( - req: Request, - res: Response, - service: UserService, - UserClass: new () => T -) { +export async function createUserHandler(req: Request, res: Response, service: UserService, UserClass: new () => T) { try { console.log('req', req); const userData = req.body as UserDTO; @@ -81,11 +66,7 @@ export async function createUserHandler( } } -export async function deleteUserHandler( - req: Request, - res: Response, - service: UserService -) { +export async function deleteUserHandler(req: Request, res: Response, service: UserService) { try { const username = req.params.username; diff --git a/backend/src/data/assignments/group-repository.ts b/backend/src/data/assignments/group-repository.ts index 56736787..eb1b09e2 100644 --- a/backend/src/data/assignments/group-repository.ts +++ b/backend/src/data/assignments/group-repository.ts @@ -4,10 +4,7 @@ import { Assignment } from '../../entities/assignments/assignment.entity.js'; import { Student } from '../../entities/users/student.entity.js'; export class GroupRepository extends DwengoEntityRepository { - public findByAssignmentAndGroupNumber( - assignment: Assignment, - groupNumber: number - ): Promise { + public findByAssignmentAndGroupNumber(assignment: Assignment, groupNumber: number): Promise { return this.findOne( { assignment: assignment, @@ -16,26 +13,16 @@ export class GroupRepository extends DwengoEntityRepository { { populate: ['members'] } ); } - public findAllGroupsForAssignment( - assignment: Assignment - ): Promise { + public findAllGroupsForAssignment(assignment: Assignment): Promise { return this.findAll({ where: { assignment: assignment }, populate: ['members'], }); } - public findAllGroupsWithStudent( - student: Student - ): Promise { - return this.find( - { members: student }, - { populate: ['members'] } - ) + public findAllGroupsWithStudent(student: Student): Promise { + return this.find({ members: student }, { populate: ['members'] }); } - public deleteByAssignmentAndGroupNumber( - assignment: Assignment, - groupNumber: number - ) { + public deleteByAssignmentAndGroupNumber(assignment: Assignment, groupNumber: number) { return this.deleteWhere({ assignment: assignment, groupNumber: groupNumber, diff --git a/backend/src/data/assignments/submission-repository.ts b/backend/src/data/assignments/submission-repository.ts index 6ec1217f..251823fa 100644 --- a/backend/src/data/assignments/submission-repository.ts +++ b/backend/src/data/assignments/submission-repository.ts @@ -5,10 +5,7 @@ import { LearningObjectIdentifier } from '../../entities/content/learning-object import { Student } from '../../entities/users/student.entity.js'; export class SubmissionRepository extends DwengoEntityRepository { - public findSubmissionByLearningObjectAndSubmissionNumber( - loId: LearningObjectIdentifier, - submissionNumber: number - ): Promise { + public findSubmissionByLearningObjectAndSubmissionNumber(loId: LearningObjectIdentifier, submissionNumber: number): Promise { return this.findOne({ learningObjectHruid: loId.hruid, learningObjectLanguage: loId.language, @@ -17,10 +14,7 @@ export class SubmissionRepository extends DwengoEntityRepository { }); } - public findMostRecentSubmissionForStudent( - loId: LearningObjectIdentifier, - submitter: Student - ): Promise { + public findMostRecentSubmissionForStudent(loId: LearningObjectIdentifier, submitter: Student): Promise { return this.findOne( { learningObjectHruid: loId.hruid, @@ -32,10 +26,7 @@ export class SubmissionRepository extends DwengoEntityRepository { ); } - public findMostRecentSubmissionForGroup( - loId: LearningObjectIdentifier, - group: Group - ): Promise { + public findMostRecentSubmissionForGroup(loId: LearningObjectIdentifier, group: Group): Promise { return this.findOne( { learningObjectHruid: loId.hruid, @@ -47,26 +38,15 @@ export class SubmissionRepository extends DwengoEntityRepository { ); } - public findAllSubmissionsForGroup( - group: Group, - ): Promise { - return this.find( - { onBehalfOf: group }, - ); + public findAllSubmissionsForGroup(group: Group): Promise { + return this.find({ onBehalfOf: group }); } - public findAllSubmissionsForStudent( - student: Student, - ): Promise { - return this.find( - { submitter: student }, - ); + public findAllSubmissionsForStudent(student: Student): Promise { + return this.find({ submitter: student }); } - public deleteSubmissionByLearningObjectAndSubmissionNumber( - loId: LearningObjectIdentifier, - submissionNumber: number - ): Promise { + public deleteSubmissionByLearningObjectAndSubmissionNumber(loId: LearningObjectIdentifier, submissionNumber: number): Promise { return this.deleteWhere({ learningObjectHruid: loId.hruid, learningObjectLanguage: loId.language, diff --git a/backend/src/data/classes/class-repository.ts b/backend/src/data/classes/class-repository.ts index 4f2f5b0e..0ceed98e 100644 --- a/backend/src/data/classes/class-repository.ts +++ b/backend/src/data/classes/class-repository.ts @@ -5,10 +5,7 @@ import { Teacher } from '../../entities/users/teacher.entity'; export class ClassRepository extends DwengoEntityRepository { public findById(id: string): Promise { - return this.findOne( - { classId: id }, - { populate: ['students', 'teachers'] } - ); + return this.findOne({ classId: id }, { populate: ['students', 'teachers'] }); } public deleteById(id: string): Promise { return this.deleteWhere({ classId: id }); @@ -21,9 +18,6 @@ export class ClassRepository extends DwengoEntityRepository { } public findByTeacher(teacher: Teacher): Promise { - return this.find( - { teachers: teacher }, - { populate: ['students', 'teachers'] } - ); + return this.find({ teachers: teacher }, { populate: ['students', 'teachers'] }); } } diff --git a/backend/src/data/questions/answer-repository.ts b/backend/src/data/questions/answer-repository.ts index 0e20e479..a28342bd 100644 --- a/backend/src/data/questions/answer-repository.ts +++ b/backend/src/data/questions/answer-repository.ts @@ -19,10 +19,7 @@ export class AnswerRepository extends DwengoEntityRepository { orderBy: { sequenceNumber: 'ASC' }, }); } - public removeAnswerByQuestionAndSequenceNumber( - question: Question, - sequenceNumber: number - ): Promise { + public removeAnswerByQuestionAndSequenceNumber(question: Question, sequenceNumber: number): Promise { return this.deleteWhere({ toQuestion: question, sequenceNumber: sequenceNumber, diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index e24d48b8..9207e1dd 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -21,9 +21,7 @@ export class QuestionRepository extends DwengoEntityRepository { questionEntity.content = question.content; return this.insert(questionEntity); } - public findAllQuestionsAboutLearningObject( - loId: LearningObjectIdentifier - ): Promise { + public findAllQuestionsAboutLearningObject(loId: LearningObjectIdentifier): Promise { return this.findAll({ where: { learningObjectHruid: loId.hruid, @@ -35,10 +33,7 @@ export class QuestionRepository extends DwengoEntityRepository { }, }); } - public removeQuestionByLearningObjectAndSequenceNumber( - loId: LearningObjectIdentifier, - sequenceNumber: number - ): Promise { + public removeQuestionByLearningObjectAndSequenceNumber(loId: LearningObjectIdentifier, sequenceNumber: number): Promise { return this.deleteWhere({ learningObjectHruid: loId.hruid, learningObjectLanguage: loId.language, @@ -47,14 +42,12 @@ export class QuestionRepository extends DwengoEntityRepository { }); } - public async findAllByLearningObjects( - learningObjects: LearningObject[] - ): Promise { + public async findAllByLearningObjects(learningObjects: LearningObject[]): Promise { const objectIdentifiers = learningObjects.map((lo) => ({ - learningObjectHruid: lo.hruid, - learningObjectLanguage: lo.language, - learningObjectVersion: lo.version, - })); + learningObjectHruid: lo.hruid, + learningObjectLanguage: lo.language, + learningObjectVersion: lo.version, + })); return this.findAll({ where: { $or: objectIdentifiers }, diff --git a/backend/src/data/repositories.ts b/backend/src/data/repositories.ts index 0c091aa9..02385109 100644 --- a/backend/src/data/repositories.ts +++ b/backend/src/data/repositories.ts @@ -40,9 +40,7 @@ export function transactional(f: () => Promise) { entityManager?.transactional(f); } -function repositoryGetter>( - entity: EntityName -): () => R { +function repositoryGetter>(entity: EntityName): () => R { let cachedRepo: R | undefined; return (): R => { if (!cachedRepo) { diff --git a/backend/src/data/users/student-repository.ts b/backend/src/data/users/student-repository.ts index f3cf7b6a..0792678d 100644 --- a/backend/src/data/users/student-repository.ts +++ b/backend/src/data/users/student-repository.ts @@ -12,4 +12,4 @@ export class StudentRepository extends DwengoEntityRepository { public deleteByUsername(username: string): Promise { return this.deleteWhere({ username: username }); } -} \ No newline at end of file +} diff --git a/backend/src/data/users/teacher-repository.ts b/backend/src/data/users/teacher-repository.ts index 23ba559e..2b2bee75 100644 --- a/backend/src/data/users/teacher-repository.ts +++ b/backend/src/data/users/teacher-repository.ts @@ -9,4 +9,4 @@ export class TeacherRepository extends DwengoEntityRepository { public deleteByUsername(username: string): Promise { return this.deleteWhere({ username: username }); } -} \ No newline at end of file +} diff --git a/backend/src/entities/assignments/assignment.entity.ts b/backend/src/entities/assignments/assignment.entity.ts index a1f53386..692e2112 100644 --- a/backend/src/entities/assignments/assignment.entity.ts +++ b/backend/src/entities/assignments/assignment.entity.ts @@ -1,12 +1,4 @@ -import { - Collection, - Entity, - Enum, - ManyToOne, - OneToMany, - PrimaryKey, - Property, -} from '@mikro-orm/core'; +import { Collection, Entity, Enum, ManyToOne, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { Class } from '../classes/class.entity.js'; import { Group } from './group.entity.js'; import { Language } from '../content/language.js'; diff --git a/backend/src/entities/classes/class.entity.ts b/backend/src/entities/classes/class.entity.ts index a484deff..63315304 100644 --- a/backend/src/entities/classes/class.entity.ts +++ b/backend/src/entities/classes/class.entity.ts @@ -1,10 +1,4 @@ -import { - Collection, - Entity, - ManyToMany, - PrimaryKey, - Property, -} from '@mikro-orm/core'; +import { Collection, Entity, ManyToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { v4 } from 'uuid'; import { Teacher } from '../users/teacher.entity.js'; import { Student } from '../users/student.entity.js'; diff --git a/backend/src/entities/content/language.ts b/backend/src/entities/content/language.ts index 40a00919..7e7b42d2 100644 --- a/backend/src/entities/content/language.ts +++ b/backend/src/entities/content/language.ts @@ -190,4 +190,4 @@ export const languageMap: Record = { fr: Language.French, en: Language.English, de: Language.German, -}; \ No newline at end of file +}; diff --git a/backend/src/entities/content/learning-object.entity.ts b/backend/src/entities/content/learning-object.entity.ts index 4a3641bb..9eda22ba 100644 --- a/backend/src/entities/content/learning-object.entity.ts +++ b/backend/src/entities/content/learning-object.entity.ts @@ -1,13 +1,4 @@ -import { - Embeddable, - Embedded, - Entity, - Enum, - ManyToMany, - OneToMany, - PrimaryKey, - Property, -} from '@mikro-orm/core'; +import { Embeddable, Embedded, Entity, Enum, ManyToMany, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; import { Language } from './language.js'; import { Attachment } from './attachment.entity.js'; import { Teacher } from '../users/teacher.entity.js'; diff --git a/backend/src/interfaces/answer.ts b/backend/src/interfaces/answer.ts index 0b86a4d1..493fd3c0 100644 --- a/backend/src/interfaces/answer.ts +++ b/backend/src/interfaces/answer.ts @@ -1,6 +1,6 @@ -import {mapToUserDTO, UserDTO} from "./user.js"; -import {mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId} from "./question.js"; -import {Answer} from "../entities/questions/answer.entity.js"; +import { mapToUserDTO, UserDTO } from './user.js'; +import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from './question.js'; +import { Answer } from '../entities/questions/answer.entity.js'; export interface AnswerDTO { author: UserDTO; @@ -33,6 +33,6 @@ export function mapToAnswerId(answer: AnswerDTO): AnswerId { return { author: answer.author.username, toQuestion: mapToQuestionId(answer.toQuestion), - sequenceNumber: answer.sequenceNumber - } + sequenceNumber: answer.sequenceNumber, + }; } diff --git a/backend/src/interfaces/class.ts b/backend/src/interfaces/class.ts index e04ce2d4..371e3cae 100644 --- a/backend/src/interfaces/class.ts +++ b/backend/src/interfaces/class.ts @@ -27,15 +27,11 @@ export function mapToClassDTO(cls: Class): ClassDTO { }; } -export function mapToClass( - classData: ClassDTO, - students: Collection, - teachers: Collection -): Class { +export function mapToClass(classData: ClassDTO, students: Collection, teachers: Collection): Class { const cls = new Class(); cls.displayName = classData.displayName; cls.students = students; cls.teachers = teachers; - + return cls; } diff --git a/backend/src/interfaces/question.ts b/backend/src/interfaces/question.ts index 69039ee9..8cca42f6 100644 --- a/backend/src/interfaces/question.ts +++ b/backend/src/interfaces/question.ts @@ -1,6 +1,6 @@ import { Question } from '../entities/questions/question.entity.js'; -import {UserDTO} from "./user.js"; -import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; +import { UserDTO } from './user.js'; +import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { mapToStudentDTO, StudentDTO } from './student.js'; import { TeacherDTO } from './teacher.js'; @@ -19,8 +19,8 @@ export function mapToQuestionDTO(question: Question): QuestionDTO { const learningObjectIdentifier = { hruid: question.learningObjectHruid, language: question.learningObjectLanguage, - version: question.learningObjectVersion - } + version: question.learningObjectVersion, + }; return { learningObjectIdentifier, @@ -42,4 +42,3 @@ export function mapToQuestionId(question: QuestionDTO): QuestionId { sequenceNumber: question.sequenceNumber!, }; } - diff --git a/backend/src/interfaces/student.ts b/backend/src/interfaces/student.ts index 9790eb35..079b355b 100644 --- a/backend/src/interfaces/student.ts +++ b/backend/src/interfaces/student.ts @@ -23,11 +23,7 @@ export function mapToStudentDTO(student: Student): StudentDTO { } export function mapToStudent(studentData: StudentDTO): Student { - const student = new Student( - studentData.username, - studentData.firstName, - studentData.lastName, - ); + const student = new Student(studentData.username, studentData.firstName, studentData.lastName); return student; } diff --git a/backend/src/interfaces/submission.ts b/backend/src/interfaces/submission.ts index 40b76fad..fbaf520d 100644 --- a/backend/src/interfaces/submission.ts +++ b/backend/src/interfaces/submission.ts @@ -1,20 +1,20 @@ -import { Submission } from "../entities/assignments/submission.entity.js"; -import { Language } from "../entities/content/language.js"; -import { GroupDTO, mapToGroupDTO } from "./group.js"; -import {mapToStudent, mapToStudentDTO, StudentDTO} from "./student.js"; -import {mapToUser} from "./user"; -import {Student} from "../entities/users/student.entity"; +import { Submission } from '../entities/assignments/submission.entity.js'; +import { Language } from '../entities/content/language.js'; +import { GroupDTO, mapToGroupDTO } from './group.js'; +import { mapToStudent, mapToStudentDTO, StudentDTO } from './student.js'; +import { mapToUser } from './user'; +import { Student } from '../entities/users/student.entity'; export interface SubmissionDTO { - learningObjectHruid: string, - learningObjectLanguage: Language, - learningObjectVersion: number, + learningObjectHruid: string; + learningObjectLanguage: Language; + learningObjectVersion: number; - submissionNumber?: number, - submitter: StudentDTO, - time?: Date, - group?: GroupDTO, - content: string, + submissionNumber?: number; + submitter: StudentDTO; + time?: Date; + group?: GroupDTO; + content: string; } export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { @@ -28,7 +28,7 @@ export function mapToSubmissionDTO(submission: Submission): SubmissionDTO { time: submission.submissionTime, group: submission.onBehalfOf ? mapToGroupDTO(submission.onBehalfOf) : undefined, content: submission.content, - } + }; } export function mapToSubmission(submissionDTO: SubmissionDTO): Submission { @@ -37,7 +37,7 @@ export function mapToSubmission(submissionDTO: SubmissionDTO): Submission { submission.learningObjectLanguage = submissionDTO.learningObjectLanguage; submission.learningObjectVersion = submissionDTO.learningObjectVersion; // Submission.submissionNumber = submissionDTO.submissionNumber; - submission.submitter = mapToStudent(submissionDTO.submitter) ; + submission.submitter = mapToStudent(submissionDTO.submitter); // Submission.submissionTime = submissionDTO.time; // Submission.onBehalfOf = submissionDTO.group!; // TODO fix group diff --git a/backend/src/interfaces/teacher-invitation.ts b/backend/src/interfaces/teacher-invitation.ts index d29e7476..cddef566 100644 --- a/backend/src/interfaces/teacher-invitation.ts +++ b/backend/src/interfaces/teacher-invitation.ts @@ -8,9 +8,7 @@ export interface TeacherInvitationDTO { class: string | ClassDTO; } -export function mapToTeacherInvitationDTO( - invitation: TeacherInvitation -): TeacherInvitationDTO { +export function mapToTeacherInvitationDTO(invitation: TeacherInvitation): TeacherInvitationDTO { return { sender: mapToUserDTO(invitation.sender), receiver: mapToUserDTO(invitation.receiver), @@ -18,9 +16,7 @@ export function mapToTeacherInvitationDTO( }; } -export function mapToTeacherInvitationDTOIds( - invitation: TeacherInvitation -): TeacherInvitationDTO { +export function mapToTeacherInvitationDTOIds(invitation: TeacherInvitation): TeacherInvitationDTO { return { sender: invitation.sender.username, receiver: invitation.receiver.username, diff --git a/backend/src/interfaces/teacher.ts b/backend/src/interfaces/teacher.ts index 93dbf5fd..4dd6adb4 100644 --- a/backend/src/interfaces/teacher.ts +++ b/backend/src/interfaces/teacher.ts @@ -23,11 +23,7 @@ export function mapToTeacherDTO(teacher: Teacher): TeacherDTO { } export function mapToTeacher(TeacherData: TeacherDTO): Teacher { - const teacher = new Teacher( - TeacherData.username, - TeacherData.firstName, - TeacherData.lastName, - ); + const teacher = new Teacher(TeacherData.username, TeacherData.firstName, TeacherData.lastName); return teacher; } diff --git a/backend/src/interfaces/user.ts b/backend/src/interfaces/user.ts index 64081d48..58f0dd5a 100644 --- a/backend/src/interfaces/user.ts +++ b/backend/src/interfaces/user.ts @@ -22,10 +22,7 @@ export function mapToUserDTO(user: User): UserDTO { }; } -export function mapToUser( - userData: UserDTO, - userInstance: T -): T { +export function mapToUser(userData: UserDTO, userInstance: T): T { userInstance.username = userData.username; userInstance.firstName = userData.firstName; userInstance.lastName = userData.lastName; diff --git a/backend/src/routes/learning-objects.ts b/backend/src/routes/learning-objects.ts index 45e0df4c..7532765b 100644 --- a/backend/src/routes/learning-objects.ts +++ b/backend/src/routes/learning-objects.ts @@ -1,15 +1,9 @@ import express from 'express'; -import { - getAllLearningObjects, - getAttachment, - getLearningObject, - getLearningObjectHTML, -} from '../controllers/learning-objects.js'; +import { getAllLearningObjects, getAttachment, getLearningObject, getLearningObjectHTML } from '../controllers/learning-objects.js'; import submissionRoutes from './submissions.js'; import questionRoutes from './questions.js'; - const router = express.Router(); // DWENGO learning objects @@ -32,7 +26,7 @@ router.get('/:hruid', getLearningObject); router.use('/:hruid/submissions', submissionRoutes); -router.use('/:hruid/:version/questions', questionRoutes) +router.use('/:hruid/:version/questions', questionRoutes); // Parameter: hruid of learning object // Query: language, version (optional) diff --git a/backend/src/routes/questions.ts b/backend/src/routes/questions.ts index d9a4dd9d..31a71f3b 100644 --- a/backend/src/routes/questions.ts +++ b/backend/src/routes/questions.ts @@ -1,10 +1,11 @@ import express from 'express'; import { - createQuestionHandler, deleteQuestionHandler, + createQuestionHandler, + deleteQuestionHandler, getAllQuestionsHandler, getQuestionAnswersHandler, - getQuestionHandler -} from "../controllers/questions.js"; + getQuestionHandler, +} from '../controllers/questions.js'; const router = express.Router({ mergeParams: true }); // Query language diff --git a/backend/src/routes/submissions.ts b/backend/src/routes/submissions.ts index e431260f..4db93027 100644 --- a/backend/src/routes/submissions.ts +++ b/backend/src/routes/submissions.ts @@ -1,9 +1,7 @@ import express from 'express'; -import {createSubmissionHandler, deleteSubmissionHandler, getSubmissionHandler} from '../controllers/submissions.js'; +import { createSubmissionHandler, deleteSubmissionHandler, getSubmissionHandler } from '../controllers/submissions.js'; const router = express.Router({ mergeParams: true }); - - // Root endpoint used to search objects router.get('/', (req, res) => { res.json({ diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index e67c2c0c..be121810 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -1,22 +1,9 @@ -import { - getAssignmentRepository, - getClassRepository, - getGroupRepository, - getSubmissionRepository, -} from '../data/repositories.js'; +import { getAssignmentRepository, getClassRepository, getGroupRepository, getSubmissionRepository } from '../data/repositories.js'; import { Assignment } from '../entities/assignments/assignment.entity.js'; -import { - AssignmentDTO, - mapToAssignment, - mapToAssignmentDTO, - mapToAssignmentDTOId, -} from '../interfaces/assignment.js'; +import { AssignmentDTO, mapToAssignment, mapToAssignmentDTO, mapToAssignmentDTOId } from '../interfaces/assignment.js'; import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; -export async function getAllAssignments( - classid: string, - full: boolean -): Promise { +export async function getAllAssignments(classid: string, full: boolean): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classid); @@ -25,8 +12,7 @@ export async function getAllAssignments( } const assignmentRepository = getAssignmentRepository(); - const assignments = - await assignmentRepository.findAllAssignmentsInClass(cls); + const assignments = await assignmentRepository.findAllAssignmentsInClass(cls); if (full) { return assignments.map(mapToAssignmentDTO); @@ -35,14 +21,11 @@ export async function getAllAssignments( return assignments.map(mapToAssignmentDTOId); } -export async function createAssignment( - classid: string, - assignmentData: AssignmentDTO, -): Promise { +export async function createAssignment(classid: string, assignmentData: AssignmentDTO): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classid); - if (!cls) { + if (!cls) { return null; } @@ -54,16 +37,12 @@ export async function createAssignment( await assignmentRepository.save(newAssignment); return newAssignment; - } catch(e) { + } catch (e) { return null; } - } -export async function getAssignment( - classid: string, - id: number -): Promise { +export async function getAssignment(classid: string, id: number): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classid); @@ -81,10 +60,7 @@ export async function getAssignment( return mapToAssignmentDTO(assignment); } -export async function getAssignmentsSubmissions( - classid: string, - assignmentNumber: number, -): Promise { +export async function getAssignmentsSubmissions(classid: string, assignmentNumber: number): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classid); @@ -103,8 +79,7 @@ export async function getAssignmentsSubmissions( const groups = await groupRepository.findAllGroupsForAssignment(assignment); const submissionRepository = getSubmissionRepository(); - const submissions = - (await Promise.all(groups.map(group => submissionRepository.findAllSubmissionsForGroup(group)))).flat(); + const submissions = (await Promise.all(groups.map((group) => submissionRepository.findAllSubmissionsForGroup(group)))).flat(); return submissions.map(mapToSubmissionDTO); -} \ No newline at end of file +} diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 4b76d0cd..46530327 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -1,26 +1,12 @@ -import { - getClassRepository, - getStudentRepository, - getTeacherInvitationRepository, - getTeacherRepository, -} from '../data/repositories.js'; +import { getClassRepository, getStudentRepository, getTeacherInvitationRepository, getTeacherRepository } from '../data/repositories.js'; import { Class } from '../entities/classes/class.entity.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; -import { - mapToTeacherInvitationDTO, - mapToTeacherInvitationDTOIds, - TeacherInvitationDTO, -} from '../interfaces/teacher-invitation.js'; +import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from '../interfaces/teacher-invitation.js'; -export async function getAllClasses( - full: boolean -): Promise { +export async function getAllClasses(full: boolean): Promise { const classRepository = getClassRepository(); - const classes = await classRepository.find( - {}, - { populate: ['students', 'teachers'] } - ); + const classes = await classRepository.find({}, { populate: ['students', 'teachers'] }); if (!classes) { return []; @@ -35,13 +21,11 @@ export async function getAllClasses( export async function createClass(classData: ClassDTO): Promise { const teacherRepository = getTeacherRepository(); const teacherUsernames = classData.teachers || []; - const teachers = (await Promise.all(teacherUsernames.map(id => teacherRepository.findByUsername(id)))) - .filter(teacher => teacher != null); + const teachers = (await Promise.all(teacherUsernames.map((id) => teacherRepository.findByUsername(id)))).filter((teacher) => teacher != null); const studentRepository = getStudentRepository(); const studentUsernames = classData.students || []; - const students = (await Promise.all(studentUsernames.map(id => studentRepository.findByUsername(id)))) - .filter(student => student != null); + const students = (await Promise.all(studentUsernames.map((id) => studentRepository.findByUsername(id)))).filter((student) => student != null); //Const cls = mapToClass(classData, teachers, students); @@ -56,7 +40,7 @@ export async function createClass(classData: ClassDTO): Promise { await classRepository.save(newClass); return newClass; - } catch(e) { + } catch (e) { return null; } } @@ -92,10 +76,7 @@ export async function getClassStudentsIds(classId: string): Promise { return students.map((student) => student.username); } -export async function getClassTeacherInvitations( - classId: string, - full: boolean -): Promise { +export async function getClassTeacherInvitations(classId: string, full: boolean): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); @@ -104,8 +85,7 @@ export async function getClassTeacherInvitations( } const teacherInvitationRepository = getTeacherInvitationRepository(); - const invitations = - await teacherInvitationRepository.findAllInvitationsForClass(cls); + const invitations = await teacherInvitationRepository.findAllInvitationsForClass(cls); if (full) { return invitations.map(mapToTeacherInvitationDTO); diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index 2f2d0a14..91091703 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -7,19 +7,10 @@ import { getSubmissionRepository, } from '../data/repositories.js'; import { Group } from '../entities/assignments/group.entity.js'; -import { - GroupDTO, - mapToGroupDTO, - mapToGroupDTOId, -} from '../interfaces/group.js'; +import { GroupDTO, mapToGroupDTO, mapToGroupDTOId } from '../interfaces/group.js'; import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; -export async function getGroup( - classId: string, - assignmentNumber: number, - groupNumber: number, - full: boolean -): Promise { +export async function getGroup(classId: string, assignmentNumber: number, groupNumber: number, full: boolean): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); @@ -28,20 +19,14 @@ export async function getGroup( } const assignmentRepository = getAssignmentRepository(); - const assignment = await assignmentRepository.findByClassAndId( - cls, - assignmentNumber - ); + const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); if (!assignment) { return null; } const groupRepository = getGroupRepository(); - const group = await groupRepository.findByAssignmentAndGroupNumber( - assignment, - groupNumber - ); + const group = await groupRepository.findByAssignmentAndGroupNumber(assignment, groupNumber); if (!group) { return null; @@ -54,16 +39,11 @@ export async function getGroup( return mapToGroupDTOId(group); } -export async function createGroup( - groupData: GroupDTO, - classid: string, - assignmentNumber: number, -): Promise { +export async function createGroup(groupData: GroupDTO, classid: string, assignmentNumber: number): Promise { const studentRepository = getStudentRepository(); - const memberUsernames = groupData.members as string[] || []; // TODO check if groupdata.members is a list - const members = (await Promise.all([...memberUsernames].map(id => studentRepository.findByUsername(id)))) - .filter(student => student != null); + const memberUsernames = (groupData.members as string[]) || []; // TODO check if groupdata.members is a list + const members = (await Promise.all([...memberUsernames].map((id) => studentRepository.findByUsername(id)))).filter((student) => student != null); console.log(members); @@ -90,17 +70,13 @@ export async function createGroup( await groupRepository.save(newGroup); return newGroup; - } catch(e) { + } catch (e) { console.log(e); return null; } } -export async function getAllGroups( - classId: string, - assignmentNumber: number, - full: boolean -): Promise { +export async function getAllGroups(classId: string, assignmentNumber: number, full: boolean): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); @@ -109,10 +85,7 @@ export async function getAllGroups( } const assignmentRepository = getAssignmentRepository(); - const assignment = await assignmentRepository.findByClassAndId( - cls, - assignmentNumber - ); + const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); if (!assignment) { return []; @@ -130,11 +103,7 @@ export async function getAllGroups( return groups.map(mapToGroupDTOId); } -export async function getGroupSubmissions( - classId: string, - assignmentNumber: number, - groupNumber: number, -): Promise { +export async function getGroupSubmissions(classId: string, assignmentNumber: number, groupNumber: number): Promise { const classRepository = getClassRepository(); const cls = await classRepository.findById(classId); @@ -143,20 +112,14 @@ export async function getGroupSubmissions( } const assignmentRepository = getAssignmentRepository(); - const assignment = await assignmentRepository.findByClassAndId( - cls, - assignmentNumber - ); + const assignment = await assignmentRepository.findByClassAndId(cls, assignmentNumber); if (!assignment) { return []; } const groupRepository = getGroupRepository(); - const group = await groupRepository.findByAssignmentAndGroupNumber( - assignment, - groupNumber - ); + const group = await groupRepository.findByAssignmentAndGroupNumber(assignment, groupNumber); if (!group) { return []; diff --git a/backend/src/services/learning-objects.ts b/backend/src/services/learning-objects.ts index dfde4da7..fb579471 100644 --- a/backend/src/services/learning-objects.ts +++ b/backend/src/services/learning-objects.ts @@ -1,16 +1,8 @@ import { DWENGO_API_BASE } from '../config.js'; import { fetchWithLogging } from '../util/api-helper.js'; -import { - FilteredLearningObject, - LearningObjectMetadata, - LearningObjectNode, - LearningPathResponse, -} from '../interfaces/learning-content.js'; +import { FilteredLearningObject, LearningObjectMetadata, LearningObjectNode, LearningPathResponse } from '../interfaces/learning-content.js'; -function filterData( - data: LearningObjectMetadata, - htmlUrl: string -): FilteredLearningObject { +function filterData(data: LearningObjectMetadata, htmlUrl: string): FilteredLearningObject { return { key: data.hruid, // Hruid learningObject (not path) _id: data._id, @@ -37,10 +29,7 @@ function filterData( /** * Fetches a single learning object by its HRUID */ -export async function getLearningObjectById( - hruid: string, - language: string -): Promise { +export async function getLearningObjectById(hruid: string, language: string): Promise { const metadataUrl = `${DWENGO_API_BASE}/learningObject/getMetadata?hruid=${hruid}&language=${language}`; const metadata = await fetchWithLogging( metadataUrl, @@ -59,26 +48,12 @@ export async function getLearningObjectById( /** * Generic function to fetch learning objects (full data or just HRUIDs) */ -async function fetchLearningObjects( - hruid: string, - full: boolean, - language: string -): Promise { +async function fetchLearningObjects(hruid: string, full: boolean, language: string): Promise { try { - const learningPathResponse: LearningPathResponse = - await fetchLearningPaths( - [hruid], - language, - `Learning path for HRUID "${hruid}"` - ); + const learningPathResponse: LearningPathResponse = await fetchLearningPaths([hruid], language, `Learning path for HRUID "${hruid}"`); - if ( - !learningPathResponse.success || - !learningPathResponse.data?.length - ) { - console.error( - `⚠️ WARNING: Learning path "${hruid}" exists but contains no learning objects.` - ); + if (!learningPathResponse.success || !learningPathResponse.data?.length) { + console.error(`⚠️ WARNING: Learning path "${hruid}" exists but contains no learning objects.`); return []; } @@ -88,12 +63,9 @@ async function fetchLearningObjects( return nodes.map((node) => node.learningobject_hruid); } - return await Promise.all( - nodes.map(async (node) => getLearningObjectById( - node.learningobject_hruid, - language - )) - ).then((objects) => objects.filter((obj): obj is FilteredLearningObject => obj !== null)); + return await Promise.all(nodes.map(async (node) => getLearningObjectById(node.learningobject_hruid, language))).then((objects) => + objects.filter((obj): obj is FilteredLearningObject => obj !== null) + ); } catch (error) { console.error('❌ Error fetching learning objects:', error); return []; @@ -103,27 +75,16 @@ async function fetchLearningObjects( /** * Fetch full learning object data (metadata) */ -export async function getLearningObjectsFromPath( - hruid: string, - language: string -): Promise { - return (await fetchLearningObjects( - hruid, - true, - language - )) as FilteredLearningObject[]; +export async function getLearningObjectsFromPath(hruid: string, language: string): Promise { + return (await fetchLearningObjects(hruid, true, language)) as FilteredLearningObject[]; } /** * Fetch only learning object HRUIDs */ -export async function getLearningObjectIdsFromPath( - hruid: string, - language: string -): Promise { +export async function getLearningObjectIdsFromPath(hruid: string, language: string): Promise { return (await fetchLearningObjects(hruid, false, language)) as string[]; } function fetchLearningPaths(arg0: string[], language: string, arg2: string): LearningPathResponse | PromiseLike { throw new Error('Function not implemented.'); } - diff --git a/backend/src/services/questions.ts b/backend/src/services/questions.ts index 238ebd45..ee003bcd 100644 --- a/backend/src/services/questions.ts +++ b/backend/src/services/questions.ts @@ -1,17 +1,15 @@ -import {getAnswerRepository, getQuestionRepository} from "../data/repositories.js"; -import {mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId} from "../interfaces/question.js"; -import {Question} from "../entities/questions/question.entity.js"; -import {Answer} from "../entities/questions/answer.entity.js"; -import {mapToAnswerDTO, mapToAnswerId} from "../interfaces/answer.js"; -import {QuestionRepository} from "../data/questions/question-repository.js"; -import {LearningObjectIdentifier} from "../entities/content/learning-object-identifier.js"; -import {mapToUser} from "../interfaces/user.js"; -import {Student} from "../entities/users/student.entity.js"; -import { mapToStudent } from "../interfaces/student.js"; +import { getAnswerRepository, getQuestionRepository } from '../data/repositories.js'; +import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; +import { Question } from '../entities/questions/question.entity.js'; +import { Answer } from '../entities/questions/answer.entity.js'; +import { mapToAnswerDTO, mapToAnswerId } from '../interfaces/answer.js'; +import { QuestionRepository } from '../data/questions/question-repository.js'; +import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; +import { mapToUser } from '../interfaces/user.js'; +import { Student } from '../entities/users/student.entity.js'; +import { mapToStudent } from '../interfaces/student.js'; -export async function getAllQuestions( - id: LearningObjectIdentifier, full: boolean -): Promise { +export async function getAllQuestions(id: LearningObjectIdentifier, full: boolean): Promise { const questionRepository: QuestionRepository = getQuestionRepository(); const questions = await questionRepository.findAllQuestionsAboutLearningObject(id); @@ -19,7 +17,7 @@ export async function getAllQuestions( return []; } - const questionsDTO: QuestionDTO[] = questions.map(mapToQuestionDTO); + const questionsDTO: QuestionDTO[] = questions.map(mapToQuestionDTO); if (full) { return questionsDTO; @@ -31,21 +29,20 @@ export async function getAllQuestions( async function fetchQuestion(questionId: QuestionId): Promise { const questionRepository = getQuestionRepository(); - return await questionRepository.findOne( - { - learningObjectHruid: questionId.learningObjectIdentifier.hruid, - learningObjectLanguage: questionId.learningObjectIdentifier.language, - learningObjectVersion: questionId.learningObjectIdentifier.version, - sequenceNumber: questionId.sequenceNumber - } - ) + return await questionRepository.findOne({ + learningObjectHruid: questionId.learningObjectIdentifier.hruid, + learningObjectLanguage: questionId.learningObjectIdentifier.language, + learningObjectVersion: questionId.learningObjectIdentifier.version, + sequenceNumber: questionId.sequenceNumber, + }); } export async function getQuestion(questionId: QuestionId): Promise { const question = await fetchQuestion(questionId); - if (!question) - {return null} + if (!question) { + return null; + } return mapToQuestionDTO(question); } @@ -54,18 +51,21 @@ export async function getAnswersByQuestion(questionId: QuestionId, full: boolean const answerRepository = getAnswerRepository(); const question = await fetchQuestion(questionId); - if (!question) - {return [];} + if (!question) { + return []; + } const answers: Answer[] = await answerRepository.findAllAnswersToQuestion(question); - if (!answers) - {return []} + if (!answers) { + return []; + } const answersDTO = answers.map(mapToAnswerDTO); - if (full) - {return answersDTO} + if (full) { + return answersDTO; + } return answersDTO.map(mapToAnswerId); } @@ -79,10 +79,10 @@ export async function createQuestion(questionDTO: QuestionDTO) { await questionRepository.createQuestion({ loId: questionDTO.learningObjectIdentifier, author, - content: questionDTO.content } - ); + content: questionDTO.content, + }); } catch (e) { - return null + return null; } return questionDTO; @@ -93,18 +93,15 @@ export async function deleteQuestion(questionId: QuestionId) { const question = await fetchQuestion(questionId); - if (!question) - {return null} - - try { - await questionRepository.removeQuestionByLearningObjectAndSequenceNumber( - questionId.learningObjectIdentifier, questionId.sequenceNumber - ); - } catch (e) { - return null + if (!question) { + return null; } - return question + try { + await questionRepository.removeQuestionByLearningObjectAndSequenceNumber(questionId.learningObjectIdentifier, questionId.sequenceNumber); + } catch (e) { + return null; + } + + return question; } - - diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index 3b677a10..5099a18d 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,9 +1,4 @@ -import { - getClassRepository, - getGroupRepository, - getStudentRepository, - getSubmissionRepository, -} from '../data/repositories.js'; +import { getClassRepository, getGroupRepository, getStudentRepository, getSubmissionRepository } from '../data/repositories.js'; import { Class } from '../entities/classes/class.entity.js'; import { Student } from '../entities/users/student.entity.js'; import { AssignmentDTO } from '../interfaces/assignment.js'; @@ -14,7 +9,6 @@ import { mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; import { getAllAssignments } from './assignments.js'; import { UserService } from './users.js'; - export async function getAllStudents(): Promise { const studentRepository = getStudentRepository(); const users = await studentRepository.findAll(); @@ -38,9 +32,9 @@ export async function createStudent(userData: StudentDTO): Promise await getAllAssignments(cls.classId!, full)) - ) - ).flat(); + const assignments = (await Promise.all(classes.map(async (cls) => await getAllAssignments(cls.classId!, full)))).flat(); return assignments; } @@ -121,9 +111,7 @@ export async function getStudentGroups(username: string, full: boolean): Promise return groups.map(mapToGroupDTOId); } -export async function getStudentSubmissions( - username: string -): Promise { +export async function getStudentSubmissions(username: string): Promise { const studentRepository = getStudentRepository(); const student = await studentRepository.findByUsername(username); @@ -135,4 +123,4 @@ export async function getStudentSubmissions( const submissions = await submissionRepository.findAllSubmissionsForStudent(student); return submissions.map(mapToSubmissionDTO); -} \ No newline at end of file +} diff --git a/backend/src/services/submissions.ts b/backend/src/services/submissions.ts index c9135001..a8fa96c7 100644 --- a/backend/src/services/submissions.ts +++ b/backend/src/services/submissions.ts @@ -1,13 +1,13 @@ -import {getGroupRepository, getSubmissionRepository} from "../data/repositories.js"; -import { Language } from "../entities/content/language.js"; -import { LearningObjectIdentifier } from "../entities/content/learning-object-identifier.js"; -import {mapToSubmission, mapToSubmissionDTO, SubmissionDTO} from "../interfaces/submission.js"; +import { getGroupRepository, getSubmissionRepository } from '../data/repositories.js'; +import { Language } from '../entities/content/language.js'; +import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; +import { mapToSubmission, mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; export async function getSubmission( learningObjectHruid: string, language: Language, version: number, - submissionNumber: number, + submissionNumber: number ): Promise { const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); @@ -29,29 +29,23 @@ export async function createSubmission(submissionDTO: SubmissionDTO) { const newSubmission = await submissionRepository.create(submission); await submissionRepository.save(newSubmission); } catch (e) { - return null + return null; } return submission; } -export async function deleteSubmission( - learningObjectHruid: string, - language: Language, - version: number, - submissionNumber: number -) { +export async function deleteSubmission(learningObjectHruid: string, language: Language, version: number, submissionNumber: number) { const submissionRepository = getSubmissionRepository(); const submission = getSubmission(learningObjectHruid, language, version, submissionNumber); - if (!submission) - {return null} + if (!submission) { + return null; + } const loId = new LearningObjectIdentifier(learningObjectHruid, language, version); await submissionRepository.deleteSubmissionByLearningObjectAndSubmissionNumber(loId, submissionNumber); return submission; } - - diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 2f462ed9..f4dbedfe 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -9,12 +9,7 @@ import { Teacher } from '../entities/users/teacher.entity.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { getClassStudents } from './class.js'; import { StudentDTO } from '../interfaces/student.js'; -import { - mapToQuestionDTO, - mapToQuestionId, - QuestionDTO, - QuestionId, -} from '../interfaces/question.js'; +import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; import { UserService } from './users.js'; import { mapToUser } from '../interfaces/user.js'; import { mapToTeacher, mapToTeacherDTO, TeacherDTO } from '../interfaces/teacher.js'; @@ -42,9 +37,9 @@ export async function createTeacher(userData: TeacherDTO): Promise export async function fetchStudentsByTeacher(username: string) { const classes = await getClassIdsByTeacher(username); - return ( - await Promise.all( - classes.map(async (id) => getClassStudents(id)) - ) - ).flat(); + return (await Promise.all(classes.map(async (id) => getClassStudents(id)))).flat(); } export async function getStudentsByTeacher(username: string): Promise { @@ -122,10 +113,7 @@ export async function fetchTeacherQuestions(username: string): Promise Date: Thu, 13 Mar 2025 19:27:34 +0100 Subject: [PATCH 42/49] fix: DELETE en POST endpoints toegevoegd --- backend/config.js | 8 ++++++++ backend/src/app.ts | 2 ++ backend/src/controllers/assignments.ts | 2 +- backend/src/controllers/students.ts | 6 ++---- backend/src/routes/students.ts | 2 ++ backend/src/routes/teachers.ts | 2 ++ 6 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 backend/config.js diff --git a/backend/config.js b/backend/config.js new file mode 100644 index 00000000..b9776fa9 --- /dev/null +++ b/backend/config.js @@ -0,0 +1,8 @@ +// Can be placed in dotenv but found it redundant +// Import dotenv from "dotenv"; +// Load .env file +// Dotenv.config(); +export const DWENGO_API_BASE = 'https://dwengo.org/backend/api'; +export const FALLBACK_LANG = 'nl'; +export const FALLBACK_SEQ_NUM = 1; + diff --git a/backend/src/app.ts b/backend/src/app.ts index abb2bbbc..ede3dddf 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -6,6 +6,7 @@ import learningPathRoutes from './routes/learning-paths.js'; import learningObjectRoutes from './routes/learning-objects.js'; import studentRouter from './routes/students.js'; +import teacherRouter from './routes/teachers.js'; import groupRouter from './routes/groups.js'; import assignmentRouter from './routes/assignments.js'; import submissionRouter from './routes/submissions.js'; @@ -38,6 +39,7 @@ app.get('/', (_, res: Response) => { }); app.use('/student', studentRouter); +app.use('/teacher', teacherRouter); app.use('/group', groupRouter); app.use('/assignment', assignmentRouter); app.use('/submission', submissionRouter); diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index b0695b85..3db0e3f1 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -26,7 +26,7 @@ export async function createAssignmentHandler(req: Request, re if (!assignmentData.description || !assignmentData.language || !assignmentData.learningPath || !assignmentData.title) { res.status(400).json({ - error: 'Missing one or more required fields: title, description, learningPath, title', + error: 'Missing one or more required fields: title, description, learningPath, language', }); return; } diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 5c17513d..274c6c55 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -2,6 +2,7 @@ import { Request, Response } from 'express'; import { createStudent, deleteStudent, + getAllStudents, getStudent, getStudentAssignments, getStudentClasses, @@ -142,7 +143,4 @@ export async function getStudentSubmissionsHandler(req: Request, res: Response): res.json({ submissions: submissions, }); -} -function getAllStudents(): StudentDTO[] | string[] | PromiseLike { - throw new Error('Function not implemented.'); -} +} \ No newline at end of file diff --git a/backend/src/routes/students.ts b/backend/src/routes/students.ts index 0c8babce..7ed7a666 100644 --- a/backend/src/routes/students.ts +++ b/backend/src/routes/students.ts @@ -17,6 +17,8 @@ router.get('/', getAllStudentsHandler); router.post('/', createStudentHandler); +router.delete('/', deleteStudentHandler); + router.delete('/:username', deleteStudentHandler); // Information about a student's profile diff --git a/backend/src/routes/teachers.ts b/backend/src/routes/teachers.ts index 8e7f709d..c04e1575 100644 --- a/backend/src/routes/teachers.ts +++ b/backend/src/routes/teachers.ts @@ -15,6 +15,8 @@ router.get('/', getAllTeachersHandler); router.post('/', createTeacherHandler); +router.delete('/', deleteTeacherHandler); + router.get('/:username', getTeacherHandler); router.delete('/:username', deleteTeacherHandler); From e1e8d475f48ca211bd79f78e265dfe0d9b055c08 Mon Sep 17 00:00:00 2001 From: Lint Action Date: Thu, 13 Mar 2025 18:28:43 +0000 Subject: [PATCH 43/49] style: fix linting issues met Prettier --- backend/config.js | 1 - backend/src/controllers/students.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/config.js b/backend/config.js index b9776fa9..be42027c 100644 --- a/backend/config.js +++ b/backend/config.js @@ -5,4 +5,3 @@ export const DWENGO_API_BASE = 'https://dwengo.org/backend/api'; export const FALLBACK_LANG = 'nl'; export const FALLBACK_SEQ_NUM = 1; - diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 274c6c55..6c253cff 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -143,4 +143,4 @@ export async function getStudentSubmissionsHandler(req: Request, res: Response): res.json({ submissions: submissions, }); -} \ No newline at end of file +} From f84c716fd346c97a55d30f38442afe84322da068 Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Thu, 13 Mar 2025 19:40:41 +0100 Subject: [PATCH 44/49] fix: database-learning-path-provider type errors gefixt --- .../database-learning-path-provider.ts | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/backend/src/services/learning-paths/database-learning-path-provider.ts b/backend/src/services/learning-paths/database-learning-path-provider.ts index fa8f42c6..8cd6807b 100644 --- a/backend/src/services/learning-paths/database-learning-path-provider.ts +++ b/backend/src/services/learning-paths/database-learning-path-provider.ts @@ -29,7 +29,7 @@ async function getLearningObjectsForNodes(nodes: LearningPathNode[]): Promise it === null)) { + if (Array.from(nullableNodesToLearningObjects.values()).some((it) => it === null)) { throw new Error('At least one of the learning objects on this path could not be found.'); } return nullableNodesToLearningObjects as Map; @@ -41,15 +41,11 @@ async function getLearningObjectsForNodes(nodes: LearningPathNode[]): Promise { const nodesToLearningObjects: Map = await getLearningObjectsForNodes(learningPath.nodes); - const targetAges = nodesToLearningObjects - .values() - .flatMap((it) => it.targetAges || []) - .toArray(); + const targetAges = Array.from(nodesToLearningObjects.values()) + .flatMap((it) => it.targetAges || []); - const keywords = nodesToLearningObjects - .values() - .flatMap((it) => it.keywords || []) - .toArray(); + const keywords = Array.from(nodesToLearningObjects.values()) + .flatMap((it) => it.keywords || []); const image = learningPath.image ? learningPath.image.toString('base64') : undefined; @@ -83,8 +79,7 @@ async function convertNodes( nodesToLearningObjects: Map, personalizedFor?: PersonalizationTarget ): Promise { - const nodesPromise = nodesToLearningObjects - .entries() + const nodesPromise = Array.from(nodesToLearningObjects.entries()) .map(async (entry) => { const [node, learningObject] = entry; const lastSubmission = personalizedFor ? await getLastSubmissionForCustomizationTarget(node, personalizedFor) : null; @@ -102,8 +97,7 @@ async function convertNodes( ) .map((trans, i) => convertTransition(trans, i, nodesToLearningObjects)), // Then convert all the transition }; - }) - .toArray(); + }); return await Promise.all(nodesPromise); } From bec69863b422b7ada9e8d26120ec7829da48dc8d Mon Sep 17 00:00:00 2001 From: Lint Action Date: Thu, 13 Mar 2025 18:41:54 +0000 Subject: [PATCH 45/49] style: fix linting issues met Prettier --- .../database-learning-path-provider.ts | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/backend/src/services/learning-paths/database-learning-path-provider.ts b/backend/src/services/learning-paths/database-learning-path-provider.ts index 8cd6807b..68986885 100644 --- a/backend/src/services/learning-paths/database-learning-path-provider.ts +++ b/backend/src/services/learning-paths/database-learning-path-provider.ts @@ -41,11 +41,9 @@ async function getLearningObjectsForNodes(nodes: LearningPathNode[]): Promise { const nodesToLearningObjects: Map = await getLearningObjectsForNodes(learningPath.nodes); - const targetAges = Array.from(nodesToLearningObjects.values()) - .flatMap((it) => it.targetAges || []); + const targetAges = Array.from(nodesToLearningObjects.values()).flatMap((it) => it.targetAges || []); - const keywords = Array.from(nodesToLearningObjects.values()) - .flatMap((it) => it.keywords || []); + const keywords = Array.from(nodesToLearningObjects.values()).flatMap((it) => it.keywords || []); const image = learningPath.image ? learningPath.image.toString('base64') : undefined; @@ -79,25 +77,24 @@ async function convertNodes( nodesToLearningObjects: Map, personalizedFor?: PersonalizationTarget ): Promise { - const nodesPromise = Array.from(nodesToLearningObjects.entries()) - .map(async (entry) => { - const [node, learningObject] = entry; - const lastSubmission = personalizedFor ? await getLastSubmissionForCustomizationTarget(node, personalizedFor) : null; - return { - _id: learningObject.uuid, - language: learningObject.language, - start_node: node.startNode, - created_at: node.createdAt.toISOString(), - updatedAt: node.updatedAt.toISOString(), - learningobject_hruid: node.learningObjectHruid, - version: learningObject.version, - transitions: node.transitions - .filter( - (trans) => !personalizedFor || isTransitionPossible(trans, optionalJsonStringToObject(lastSubmission?.content)) // If we want a personalized learning path, remove all transitions that aren't possible. - ) - .map((trans, i) => convertTransition(trans, i, nodesToLearningObjects)), // Then convert all the transition - }; - }); + const nodesPromise = Array.from(nodesToLearningObjects.entries()).map(async (entry) => { + const [node, learningObject] = entry; + const lastSubmission = personalizedFor ? await getLastSubmissionForCustomizationTarget(node, personalizedFor) : null; + return { + _id: learningObject.uuid, + language: learningObject.language, + start_node: node.startNode, + created_at: node.createdAt.toISOString(), + updatedAt: node.updatedAt.toISOString(), + learningobject_hruid: node.learningObjectHruid, + version: learningObject.version, + transitions: node.transitions + .filter( + (trans) => !personalizedFor || isTransitionPossible(trans, optionalJsonStringToObject(lastSubmission?.content)) // If we want a personalized learning path, remove all transitions that aren't possible. + ) + .map((trans, i) => convertTransition(trans, i, nodesToLearningObjects)), // Then convert all the transition + }; + }); return await Promise.all(nodesPromise); } From 6e7a03f55b681166fd76ac157fa1fa0eb78dd696 Mon Sep 17 00:00:00 2001 From: Gerald Schmittinger Date: Thu, 13 Mar 2025 20:45:34 +0100 Subject: [PATCH 46/49] fix(backend): Aangemaakt assignment werd niet teruggegeven. Hier ontbreekte gewoon een await. --- backend/src/controllers/assignments.ts | 5 ++--- backend/src/services/class.ts | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/src/controllers/assignments.ts b/backend/src/controllers/assignments.ts index 3db0e3f1..03332469 100644 --- a/backend/src/controllers/assignments.ts +++ b/backend/src/controllers/assignments.ts @@ -1,7 +1,6 @@ import { Request, Response } from 'express'; import { createAssignment, getAllAssignments, getAssignment, getAssignmentsSubmissions } from '../services/assignments.js'; -import { AssignmentDTO, mapToAssignment, mapToAssignmentDTO } from '../interfaces/assignment.js'; -import { getAssignmentRepository, getClassRepository } from '../data/repositories.js'; +import { AssignmentDTO } from '../interfaces/assignment.js'; // Typescript is annoy with with parameter forwarding from class.ts interface AssignmentParams { @@ -31,7 +30,7 @@ export async function createAssignmentHandler(req: Request, re return; } - const assignment = createAssignment(classid, assignmentData); + const assignment = await createAssignment(classid, assignmentData); if (!assignment) { res.status(500).json({ error: 'Could not create assignment ' }); diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 46530327..390c6a32 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -3,6 +3,9 @@ import { Class } from '../entities/classes/class.entity.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from '../interfaces/teacher-invitation.js'; +import {getLogger} from "../logging/initalize"; + +const logger = getLogger(); export async function getAllClasses(full: boolean): Promise { const classRepository = getClassRepository(); @@ -41,6 +44,7 @@ export async function createClass(classData: ClassDTO): Promise { return newClass; } catch (e) { + logger.error(e); return null; } } From d9bd12f2577f2dea59d94795eaccdd2c047ef968 Mon Sep 17 00:00:00 2001 From: Lint Action Date: Thu, 13 Mar 2025 19:46:17 +0000 Subject: [PATCH 47/49] style: fix linting issues met Prettier --- backend/src/services/class.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 390c6a32..117bffec 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -3,7 +3,7 @@ import { Class } from '../entities/classes/class.entity.js'; import { ClassDTO, mapToClassDTO } from '../interfaces/class.js'; import { mapToStudentDTO, StudentDTO } from '../interfaces/student.js'; import { mapToTeacherInvitationDTO, mapToTeacherInvitationDTOIds, TeacherInvitationDTO } from '../interfaces/teacher-invitation.js'; -import {getLogger} from "../logging/initalize"; +import { getLogger } from '../logging/initalize'; const logger = getLogger(); From f199ceb945c7d5127229faf3cfbda348310c3e8f Mon Sep 17 00:00:00 2001 From: Gerald Schmittinger Date: Thu, 13 Mar 2025 21:35:55 +0100 Subject: [PATCH 48/49] fix(backend): Kleinere fouten opgelost. --- backend/src/controllers/classes.ts | 5 ++--- backend/src/controllers/groups.ts | 2 +- backend/src/entities/assignments/submission.entity.ts | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/src/controllers/classes.ts b/backend/src/controllers/classes.ts index 6fb58fb9..ca2f5698 100644 --- a/backend/src/controllers/classes.ts +++ b/backend/src/controllers/classes.ts @@ -1,7 +1,6 @@ import { Request, Response } from 'express'; import { createClass, getAllClasses, getClass, getClassStudents, getClassStudentsIds, getClassTeacherInvitations } from '../services/class.js'; -import { ClassDTO, mapToClass } from '../interfaces/class.js'; -import { getClassRepository, getStudentRepository, getTeacherRepository } from '../data/repositories.js'; +import { ClassDTO } from '../interfaces/class.js'; export async function getAllClassesHandler(req: Request, res: Response): Promise { const full = req.query.full === 'true'; @@ -38,7 +37,7 @@ export async function getClassHandler(req: Request, res: Response): Promise Date: Thu, 13 Mar 2025 21:56:02 +0100 Subject: [PATCH 49/49] fix: onnodige imports weg --- backend/src/app.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/backend/src/app.ts b/backend/src/app.ts index b6678af3..cad68420 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -1,19 +1,6 @@ import express, { Express } from 'express'; import { initORM } from './orm.js'; -import themeRoutes from './routes/themes.js'; -import learningPathRoutes from './routes/learning-paths.js'; -import learningObjectRoutes from './routes/learning-objects.js'; - -import studentRouter from './routes/students.js'; -import teacherRouter from './routes/teachers.js'; -import groupRouter from './routes/groups.js'; -import assignmentRouter from './routes/assignments.js'; -import submissionRouter from './routes/submissions.js'; -import classRouter from './routes/classes.js'; -import questionRouter from './routes/questions.js'; -import authRouter from './routes/auth.js'; - import { authenticateUser } from './middleware/auth/auth.js'; import cors from './middleware/cors.js'; import { getLogger, Logger } from './logging/initalize.js';