diff --git a/.env.example b/.env.example index 5afe160..d5bf431 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ -DATABASE_URL="postgresql://postgres:randompassword@localhost:5432/mydb?schema=public" +NODE_ENV=development -## if no password, use this instead: -# DATABASE_URL="postgresql://postgres@localhost:5432/mydb?schema=public" \ No newline at end of file +PORT=3000 + +DATABASE_URL="postgresql://postgres@localhost:5432/planifetsDB?schema=public" \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 1254834..4e693a9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,44 +1,45 @@ -module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: 'tsconfig.json', - tsconfigRootDir: __dirname, - sourceType: 'module', - }, - plugins: ['@typescript-eslint/eslint-plugin', 'import', 'simple-import-sort'], - extends: [ - 'plugin:@typescript-eslint/recommended', - 'plugin:prettier/recommended', - 'airbnb-typescript/base', - ], - root: true, - env: { - node: true, - jest: true, - }, - ignorePatterns: ['.eslintrc.js', 'dist/'], - rules: { - '@typescript-eslint/interface-name-prefix': 'off', - '@typescript-eslint/lines-between-class-members': 'off', - complexity: ['warn', { max: 10 }], - complexity: ['error', { max: 15 }], - '@typescript-eslint/explicit-member-accessibility': [ - 'error', - { - overrides: { - constructors: 'no-public', - }, - }, - ], - 'simple-import-sort/imports': 'error', - 'simple-import-sort/exports': 'error', - 'prettier/prettier': [ - 'error', - { - endOfLine: 'lf', - }, - ], - indent: 'off', - '@typescript-eslint/indent': 'off', - }, -}; +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin', 'import', 'simple-import-sort'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + 'airbnb-typescript/base', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js', 'dist/'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/lines-between-class-members': 'off', + complexity: ['warn', { max: 10 }], + complexity: ['error', { max: 15 }], + '@typescript-eslint/explicit-member-accessibility': [ + 'error', + { + overrides: { + constructors: 'no-public', + }, + }, + ], + 'simple-import-sort/imports': 'error', + 'simple-import-sort/exports': 'error', + 'prettier/prettier': [ + 'error', + { + endOfLine: 'lf', + }, + ], + '@typescript-eslint/brace-style': 'off', + indent: 'off', + '@typescript-eslint/indent': 'off', + }, +}; diff --git a/.prettierrc b/.prettierrc index 6145d88..4959830 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,7 +1,8 @@ -{ - "tabWidth": 2, - "useTabs": false, - "semi": true, - "singleQuote": true, - "trailingComma": "all" -} \ No newline at end of file +{ + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "endOfLine": "lf" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 4fc402f..3f1abb8 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,7 @@ { - "recommendations": [ - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", - "rvest.vs-code-prettier-eslint" - ] -} \ No newline at end of file + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "abians.prisma-generate-uml" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 519c62a..67e00b8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,6 @@ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "files.eol": "\n" + "files.eol": "\n", + "typescript.preferences.importModuleSpecifier": "relative", } diff --git a/package.json b/package.json index 2d2a037..b643258 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "planif-ets-backend", + "name": "planifets-backend", "version": "0.0.1", "description": "", "author": "", @@ -13,7 +13,7 @@ "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", - "lint": "eslint .", + "lint": "eslint src --ext .ts", "refresh": "rm -rf dist && rm -rf node_modules && yarn cache clean && yarn install", "prisma:generate": "prisma generate", "prisma:preview": "prisma migrate dev --create-only", @@ -35,8 +35,9 @@ "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.1", "@nestjs/core": "^10.0.0", + "@nestjs/mapped-types": "^2.0.5", "@nestjs/platform-express": "^10.0.0", - "@prisma/client": "^5.7.1", + "@prisma/client": "^5.15.0", "axios": "^1.6.8", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", @@ -69,6 +70,7 @@ "prettier": "^3.2.5", "prettier-eslint": "^16.3.0", "prisma": "^5.7.1", + "prisma-erd-generator": "^1.11.2", "source-map-support": "^0.5.21", "supertest": "^6.3.3", "ts-jest": "^29.1.0", @@ -95,4 +97,4 @@ "coverageDirectory": "../coverage", "testEnvironment": "node" } -} \ No newline at end of file +} diff --git a/prisma/ERD.svg b/prisma/ERD.svg new file mode 100644 index 0000000..71de221 --- /dev/null +++ b/prisma/ERD.svg @@ -0,0 +1 @@ +TrimesterAUTOMNEAUTOMNEETEETEHIVERHIVERSessionStringid🗝️TrimestertrimesterIntyearDateTimecreatedAtDateTimeupdatedAtCourseInstanceStringid🗝️DateTimecreatedAtDateTimeupdatedAtCourseStringid🗝️StringprogramIdStringcodeStringtitleStringdescriptionIntcreditsDateTimecreatedAtDateTimeupdatedAtCoursePrerequisiteDateTimecreatedAtDateTimeupdatedAtProgramCourseDateTimecreatedAtDateTimeupdatedAtProgramStringid🗝️IntcodeStringtitleStringcreditsIntcycleStringurlJsonprogramTypeIdsJsonhoraireCoursPdfJsonJsonplanificationPdfJsonDateTimecreatedAtDateTimeupdatedAtProgramTypeIntid🗝️Stringtitleenum:trimestercourseInstancescoursesessionprogramscourseInstancesprerequisitesprerequisiteOfcourseprerequisitecourseprogramcourses \ No newline at end of file diff --git a/prisma/migrations/20240622070105_add_program_type_table_values/migration.sql b/prisma/migrations/20240622070105_add_program_type_table_values/migration.sql new file mode 100644 index 0000000..d7419f4 --- /dev/null +++ b/prisma/migrations/20240622070105_add_program_type_table_values/migration.sql @@ -0,0 +1,23 @@ +/* + Warnings: + + - You are about to drop the column `abbreviation` on the `Program` table. All the data in the column will be lost. + - You are about to drop the column `type` on the `Program` table. All the data in the column will be lost. + - A unique constraint covering the columns `[code,title]` on the table `Program` will be added. If there are existing duplicate values, this will fail. + +*/ +-- AlterTable +ALTER TABLE "Program" DROP COLUMN "abbreviation", +DROP COLUMN "type", +ADD COLUMN "types" INTEGER[]; + +-- CreateTable +CREATE TABLE "ProgramType" ( + "id" INTEGER NOT NULL, + "title" TEXT NOT NULL, + + CONSTRAINT "ProgramType_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Program_code_title_key" ON "Program"("code", "title"); diff --git a/prisma/migrations/20240724005644_add_program_type_relation_and_update_session_table/migration.sql b/prisma/migrations/20240724005644_add_program_type_relation_and_update_session_table/migration.sql new file mode 100644 index 0000000..0c8b516 --- /dev/null +++ b/prisma/migrations/20240724005644_add_program_type_relation_and_update_session_table/migration.sql @@ -0,0 +1,34 @@ +/* + Warnings: + + - You are about to drop the column `unstructuredPrerequisites` on the `Course` table. All the data in the column will be lost. + - You are about to drop the column `types` on the `Program` table. All the data in the column will be lost. + - You are about to drop the column `name` on the `Session` table. All the data in the column will be lost. + - Added the required column `programTypeId` to the `Program` table without a default value. This is not possible if the table is not empty. + - Added the required column `trimester` to the `Session` table without a default value. This is not possible if the table is not empty. + +*/ +-- CreateEnum +CREATE TYPE "Trimester" AS ENUM ('A', 'E', 'H'); + +-- AlterTable +ALTER TABLE "Course" DROP COLUMN "unstructuredPrerequisites"; + +-- AlterTable +ALTER TABLE "Program" DROP COLUMN "types", +ADD COLUMN "programTypeId" INTEGER NOT NULL; + +-- AlterTable +CREATE SEQUENCE programtype_id_seq; +ALTER TABLE "ProgramType" ALTER COLUMN "id" SET DEFAULT nextval('programtype_id_seq'); +ALTER SEQUENCE programtype_id_seq OWNED BY "ProgramType"."id"; + +-- AlterTable +ALTER TABLE "Session" DROP COLUMN "name", +ADD COLUMN "trimester" "Trimester" NOT NULL; + +-- CreateIndex +CREATE INDEX "Program_programTypeId_idx" ON "Program"("programTypeId"); + +-- AddForeignKey +ALTER TABLE "Program" ADD CONSTRAINT "Program_programTypeId_fkey" FOREIGN KEY ("programTypeId") REFERENCES "ProgramType"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20240724060002_update_many_to_many_program_type_to_program/migration.sql b/prisma/migrations/20240724060002_update_many_to_many_program_type_to_program/migration.sql new file mode 100644 index 0000000..3b822cd --- /dev/null +++ b/prisma/migrations/20240724060002_update_many_to_many_program_type_to_program/migration.sql @@ -0,0 +1,15 @@ +/* + Warnings: + + - You are about to drop the column `programTypeId` on the `Program` table. All the data in the column will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "Program" DROP CONSTRAINT "Program_programTypeId_fkey"; + +-- DropIndex +DROP INDEX "Program_programTypeId_idx"; + +-- AlterTable +ALTER TABLE "Program" DROP COLUMN "programTypeId", +ADD COLUMN "programTypeIds" TEXT NOT NULL DEFAULT '[]'; diff --git a/prisma/migrations/20240724061353_update_program_table_add_cycle_update_program_type_type/migration.sql b/prisma/migrations/20240724061353_update_program_table_add_cycle_update_program_type_type/migration.sql new file mode 100644 index 0000000..b05004a --- /dev/null +++ b/prisma/migrations/20240724061353_update_program_table_add_cycle_update_program_type_type/migration.sql @@ -0,0 +1,16 @@ +/* + Warnings: + + - Added the required column `cycle` to the `Program` table without a default value. This is not possible if the table is not empty. + - Changed the type of `programTypeIds` on the `Program` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + +*/ +-- AlterTable +ALTER TABLE "Program" ADD COLUMN "cycle" INTEGER NOT NULL, +ALTER COLUMN "credits" SET DATA TYPE TEXT, +DROP COLUMN "programTypeIds", +ADD COLUMN "programTypeIds" JSONB NOT NULL; + +-- AlterTable +ALTER TABLE "ProgramType" ALTER COLUMN "id" DROP DEFAULT; +DROP SEQUENCE "programtype_id_seq"; diff --git a/prisma/migrations/20240803014322_update_trimester_enum/migration.sql b/prisma/migrations/20240803014322_update_trimester_enum/migration.sql new file mode 100644 index 0000000..b241af8 --- /dev/null +++ b/prisma/migrations/20240803014322_update_trimester_enum/migration.sql @@ -0,0 +1,14 @@ +/* + Warnings: + + - The values [A,E,H] on the enum `Trimester` will be removed. If these variants are still used in the database, this will fail. + +*/ +-- AlterEnum +BEGIN; +CREATE TYPE "Trimester_new" AS ENUM ('AUTOMNE', 'ETE', 'HIVER'); +ALTER TABLE "Session" ALTER COLUMN "trimester" TYPE "Trimester_new" USING ("trimester"::text::"Trimester_new"); +ALTER TYPE "Trimester" RENAME TO "Trimester_old"; +ALTER TYPE "Trimester_new" RENAME TO "Trimester"; +DROP TYPE "Trimester_old"; +COMMIT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b69dd13..eca9e6e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -5,70 +5,86 @@ generator client { provider = "prisma-client-js" } +generator erd { + provider = "prisma-erd-generator" + theme = "neutral" +} + datasource db { provider = "postgresql" url = env("DATABASE_URL") } +enum Trimester { + AUTOMNE + ETE + HIVER +} + model Session { - id String @id @default(uuid()) - name String + id String @id @default(uuid()) + trimester Trimester year Int - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt courseInstances CourseInstance[] } model CourseInstance { - id String @id @default(uuid()) + id String @id @default(uuid()) courseId String sessionId String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt course Course @relation(fields: [courseId], references: [id]) session Session @relation(fields: [sessionId], references: [id]) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + @@unique([courseId, sessionId]) @@index([courseId, sessionId]) } model Course { - id String @id @default(uuid()) - programId String - code String @unique - title String - description String - credits Int - unstructuredPrerequisites String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - programs ProgramCourse[] - courseInstances CourseInstance[] + id String @id + programId String + code String @unique + title String + description String + credits Int + programs ProgramCourse[] + courseInstances CourseInstance[] prerequisites CoursePrerequisite[] @relation("CourseToPrerequisite") prerequisiteOf CoursePrerequisite[] @relation("PrerequisiteToCourse") + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + @@index([code, programId]) } model CoursePrerequisite { courseId String - course Course @relation("CourseToPrerequisite", fields: [courseId], references: [id]) prerequisiteId String - prerequisite Course @relation("PrerequisiteToCourse", fields: [prerequisiteId], references: [id]) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + + course Course @relation("CourseToPrerequisite", fields: [courseId], references: [id]) + prerequisite Course @relation("PrerequisiteToCourse", fields: [prerequisiteId], references: [id]) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@id([courseId, prerequisiteId]) } model ProgramCourse { courseId String - course Course @relation(fields: [courseId], references: [id]) programId String - program Program @relation(fields: [programId], references: [id]) + + course Course @relation(fields: [courseId], references: [id]) + program Program @relation(fields: [programId], references: [id]) + createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -76,17 +92,24 @@ model ProgramCourse { } model Program { - id String @id @default(uuid()) - code Int @unique + id String @id + code Int @unique title String - credits Int - type String + credits String + cycle Int url String - abbreviation String? + programTypeIds Json horaireCoursPdfJson Json? planificationPdfJson Json? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + courses ProgramCourse[] + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([code, title]) +} - courses ProgramCourse[] +model ProgramType { + id Int @id + title String } diff --git a/prisma/seeds/programs/programs.json b/prisma/seeds/programs/programs.json deleted file mode 100644 index 785fc0e..0000000 --- a/prisma/seeds/programs/programs.json +++ /dev/null @@ -1,87 +0,0 @@ -[ - { - "code": "7625", - "type": "premier-cycle", - "url": "baccalaureat-genie-construction" - }, - { - "code": "7694", - "type": "premier-cycle", - "url": "baccalaureat-genie-electrique" - }, - { - "code": "7084", - "type": "premier-cycle", - "url": "baccalaureat-genie-logiciel" - }, - { - "code": "7684", - "type": "premier-cycle", - "url": "baccalaureat-genie-mecanique" - }, - { - "code": "6556", - "type": "premier-cycle", - "url": "baccalaureat-genie-operations-logistique" - }, - { - "code": "6557", - "type": "premier-cycle", - "url": "baccalaureat-genie-production-automatisee" - }, - { - "code": "7086", - "type": "premier-cycle", - "url": "baccalaureat-genie-des-ti" - }, - { - "code": "6646", - "type": "premier-cycle", - "url": "baccalaureat-informatique-distribuee" - }, - { - "code": "5766", - "type": "premier-cycle", - "url": "cheminement-universitaire-technologie" - }, - { - "code": "4567", - "type": "premier-cycle", - "url": "certificat-economie-estimation" - }, - { - "code": "4412", - "type": "premier-cycle", - "url": "certificat-gestion-assurance-qualite" - }, - { - "code": "4563", - "type": "premier-cycle", - "url": "certificat-gestion-construction" - }, - { - "code": "4684", - "type": "premier-cycle", - "url": "certificat-gestion-immobiliere" - }, - { - "code": "4329", - "type": "premier-cycle", - "url": "certificat-production-industrielle" - }, - { - "code": "4288", - "type": "premier-cycle", - "url": "certificat-telecommunications" - }, - { - "code": "1822", - "type": "deuxieme-cycle", - "url": "maitrise-genie-logiciel" - }, - { - "code": "3178", - "type": "deuxieme-cycle", - "url": "dess-technologies-information" - } -] \ No newline at end of file diff --git a/src/app.controller.ts b/src/app.controller.ts new file mode 100644 index 0000000..f56c3eb --- /dev/null +++ b/src/app.controller.ts @@ -0,0 +1,9 @@ +import { Controller, Get } from '@nestjs/common'; + +@Controller() +export class AppController { + @Get() + public getHello(): string { + return 'Hello World!'; + } +} diff --git a/src/app.module.ts b/src/app.module.ts index 1722d29..2f2c3dc 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -2,11 +2,31 @@ import { HttpModule } from '@nestjs/axios'; import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; +import { AppController } from './app.controller'; +import { EtsController } from './common/api-helper/ets/ets.controller'; +import { EtsModule } from './common/api-helper/ets/ets.module'; +import { FileUtil } from './common/utils/pdf/fileUtil'; +import { PdfController } from './common/website-helper/pdf/pdf.controller'; +import { HoraireCoursService } from './common/website-helper/pdf/pdf-parser/horaire/horaire-cours.service'; +import { PlanificationCoursService } from './common/website-helper/pdf/pdf-parser/planification/planification-cours.service'; import config from './config/configuration'; -import { PdfController } from './pdf/pdf.controller'; -import { HoraireCoursService } from './pdf/pdf-parser/horaire/horaire-cours.service'; -import { PlanificationCoursService } from './pdf/pdf-parser/planification/planification-cours.service'; -import { FileUtil } from './utils/pdf/fileUtil'; +import { CourseController } from './course/course.controller'; +import { CourseModule } from './course/course.module'; +import { CourseService } from './course/course.service'; +import { CourseInstanceController } from './course-instance/course-instance.controller'; +import { CourseInstanceModule } from './course-instance/course-instance.module'; +import { CourseInstanceService } from './course-instance/course-instance.service'; +import { CoursePrerequisiteController } from './course-prerequisite/course-prerequisite.controller'; +import { CoursePrerequisiteModule } from './course-prerequisite/course-prerequisite.module'; +import { CoursePrerequisiteService } from './course-prerequisite/course-prerequisite.service'; +import { PrismaModule } from './prisma/prisma.module'; +import { PrismaService } from './prisma/prisma.service'; +import { ProgramController } from './program/program.controller'; +import { ProgramModule } from './program/program.module'; +import { ProgramService } from './program/program.service'; +import { SessionController } from './session/session.controller'; +import { SessionModule } from './session/session.module'; +import { SessionService } from './session/session.service'; @Module({ imports: [ @@ -16,8 +36,37 @@ import { FileUtil } from './utils/pdf/fileUtil'; envFilePath: '.env', }), HttpModule, + PrismaModule, + EtsModule, + + CourseModule, + CourseInstanceModule, + CoursePrerequisiteModule, + SessionModule, + ProgramModule, + ], + providers: [ + PrismaService, + FileUtil, + HoraireCoursService, + PlanificationCoursService, + + CourseService, + CourseInstanceService, + CoursePrerequisiteService, + ProgramService, + SessionService, + ], + controllers: [ + AppController, + PdfController, + EtsController, + + CourseController, + CourseInstanceController, + CoursePrerequisiteController, + ProgramController, + SessionController, ], - providers: [HoraireCoursService, PlanificationCoursService, FileUtil], - controllers: [PdfController], }) export class AppModule {} diff --git a/src/common/api-helper/ets/course/ets-course.controller.ts b/src/common/api-helper/ets/course/ets-course.controller.ts new file mode 100644 index 0000000..681ee32 --- /dev/null +++ b/src/common/api-helper/ets/course/ets-course.controller.ts @@ -0,0 +1,26 @@ +import { Controller, Get, Param } from '@nestjs/common'; + +import { + EtsCourseService, + IEtsCourse, + IEtsCoursesData, +} from './ets-course.service'; + +@Controller('ets/courses') +export class EtsCourseController { + constructor(private readonly etsCourseService: EtsCourseService) {} + + @Get() + public fetchAllCourses(): Promise { + return this.etsCourseService.fetchAllCourses(); + } + + @Get(':id') + public fetchCoursesById(@Param('id') id: string): Promise { + if (!id) { + throw new Error('The id parameter is required'); + } + + return this.etsCourseService.fetchCoursesById(id); + } +} diff --git a/src/common/api-helper/ets/course/ets-course.service.ts b/src/common/api-helper/ets/course/ets-course.service.ts new file mode 100644 index 0000000..5cb3032 --- /dev/null +++ b/src/common/api-helper/ets/course/ets-course.service.ts @@ -0,0 +1,56 @@ +import { HttpService } from '@nestjs/axios'; +import { Injectable } from '@nestjs/common'; +import { firstValueFrom } from 'rxjs'; + +import { + ETS_API_GET_ALL_COURSES, + ETS_API_GET_COURSES_BY_IDS, +} from '../../../constants/url'; + +export interface IEtsCoursesData { + id: number; + title: string; + code: string; + cycle: string | null; +} + +export interface IEtsCourse extends IEtsCoursesData { + credits: string; +} + +@Injectable() +export class EtsCourseService { + constructor(private readonly httpService: HttpService) {} + + // Fetches all courses + public async fetchAllCourses(): Promise { + const response = await firstValueFrom( + this.httpService.get(ETS_API_GET_ALL_COURSES), + ); + + const courses = response.data.results; + return courses.map((course: IEtsCoursesData) => ({ + id: course.id, + title: course.title, + code: course.code, + cycle: course.cycle, + })); + } + + // Fetches one or more courses by their ids + // The ids are passed as a string with comma-separated values, ex: "349682,349710" + public async fetchCoursesById(ids: string): Promise { + const response = await firstValueFrom( + this.httpService.get(`${ETS_API_GET_COURSES_BY_IDS}${ids}`), + ); + + const courses = response.data; + return courses.map((course: IEtsCourse) => ({ + id: course.id, + title: course.title, + code: course.code, + cycle: course.cycle, + credits: course.credits, + })); + } +} diff --git a/src/common/api-helper/ets/ets.controller.ts b/src/common/api-helper/ets/ets.controller.ts new file mode 100644 index 0000000..33ddd92 --- /dev/null +++ b/src/common/api-helper/ets/ets.controller.ts @@ -0,0 +1,35 @@ +import { Controller, Get, Param } from '@nestjs/common'; + +import { + EtsCourseService, + IEtsCourse, + IEtsCoursesData, +} from './course/ets-course.service'; +import { EtsProgramService } from './program/ets-program.service'; + +@Controller('ets') +export class EtsController { + constructor( + private readonly etsCourseService: EtsCourseService, + private readonly etsProgramService: EtsProgramService, + ) {} + + @Get('courses') + public fetchAllCourses(): Promise { + return this.etsCourseService.fetchAllCourses(); + } + + @Get('courses/:id') + public fetchCoursesById(@Param('id') id: string): Promise { + if (!id) { + throw new Error('The id parameter is required'); + } + + return this.etsCourseService.fetchCoursesById(id); + } + + @Get('programs') + public async fetchAllPrograms() { + return this.etsProgramService.fetchAllPrograms(); + } +} diff --git a/src/common/api-helper/ets/ets.module.ts b/src/common/api-helper/ets/ets.module.ts new file mode 100644 index 0000000..5d1588b --- /dev/null +++ b/src/common/api-helper/ets/ets.module.ts @@ -0,0 +1,14 @@ +import { HttpModule } from '@nestjs/axios'; +import { Module } from '@nestjs/common'; + +import { EtsCourseService } from './course/ets-course.service'; +import { EtsController } from './ets.controller'; +import { EtsProgramService } from './program/ets-program.service'; + +@Module({ + imports: [HttpModule], + controllers: [EtsController], + providers: [EtsCourseService, EtsProgramService], + exports: [EtsCourseService, EtsProgramService], +}) +export class EtsModule {} diff --git a/src/common/api-helper/ets/header.interceptor.ts b/src/common/api-helper/ets/header.interceptor.ts new file mode 100644 index 0000000..0b222f8 --- /dev/null +++ b/src/common/api-helper/ets/header.interceptor.ts @@ -0,0 +1,26 @@ +import { HttpService } from '@nestjs/axios'; +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, +} from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +@Injectable() +export class HeaderInterceptor implements NestInterceptor { + constructor(private readonly httpService: HttpService) { + this.httpService.axiosRef.interceptors.request.use((config) => { + config.headers.Accept = 'application/json'; + return config; + }); + } + + public intercept( + context: ExecutionContext, + next: CallHandler, + ): Observable { + return next.handle().pipe(map((data) => data)); + } +} diff --git a/src/common/api-helper/ets/program/ets-program.service.ts b/src/common/api-helper/ets/program/ets-program.service.ts new file mode 100644 index 0000000..78636df --- /dev/null +++ b/src/common/api-helper/ets/program/ets-program.service.ts @@ -0,0 +1,49 @@ +import { HttpService } from '@nestjs/axios'; +import { Injectable } from '@nestjs/common'; +import { firstValueFrom } from 'rxjs'; + +import { ETS_API_GET_ALL_PROGRAMS } from '../../../constants/url'; + +type Program = { + id: number; + title: string; + cycle: string; + code: string; + credits: string; + types: number[]; + url: string; +}; + +export interface ProgramType { + id: number; + title: string; +} + +@Injectable() +export class EtsProgramService { + constructor(private readonly httpService: HttpService) {} + + public async fetchAllPrograms(): Promise<{ + types: ProgramType[]; + programs: Program[]; + }> { + const response = await firstValueFrom( + this.httpService.get(ETS_API_GET_ALL_PROGRAMS), + ); + + const types: ProgramType[] = response.data.types; + const programs: Program[] = response.data.results.map( + (program: Program) => ({ + id: program.id, + title: program.title, + cycle: program.cycle, + code: program.code, + credits: program.credits, + types: program.types, + url: program.url, + }), + ); + + return { types, programs }; + } +} diff --git a/src/constants/error-messages.ts b/src/common/constants/error-messages.ts similarity index 100% rename from src/constants/error-messages.ts rename to src/common/constants/error-messages.ts diff --git a/src/common/constants/url.ts b/src/common/constants/url.ts new file mode 100644 index 0000000..c879fbe --- /dev/null +++ b/src/common/constants/url.ts @@ -0,0 +1,18 @@ +export const ETS_BASE_URL = 'https://www.etsmtl.ca/'; + +/* + * ETS website + */ +export const PROGRAM_BASE_URL = `${ETS_BASE_URL}etude/`; +export const COURSE_BASE_URL = `${ETS_BASE_URL}cours/`; + +/* + * ETS API + */ +export const ETS_API_BASE_URL = `${ETS_BASE_URL}api/`; + +export const ETS_API_GET_ALL_PROGRAMS = `${ETS_API_BASE_URL}search/programme-index`; +export const ETS_API_GET_COURSES_BY_IDS = `${ETS_API_BASE_URL}courses/get?ids=`; +export const ETS_API_GET_ALL_COURSES = `${ETS_API_BASE_URL}search/cours-index`; + +export const ETS_API_GET_ALL_DEPARTEMENTS = `${ETS_API_BASE_URL}search?s="departement="`; diff --git a/src/common/exceptions/dtos/uuid.dto.ts b/src/common/exceptions/dtos/uuid.dto.ts new file mode 100644 index 0000000..e2bb472 --- /dev/null +++ b/src/common/exceptions/dtos/uuid.dto.ts @@ -0,0 +1,6 @@ +import { IsUUID } from 'class-validator'; + +export class UuidDto { + @IsUUID() + public id!: string; +} diff --git a/src/http-exception.filter.ts b/src/common/exceptions/http-exception.filter.ts similarity index 100% rename from src/http-exception.filter.ts rename to src/common/exceptions/http-exception.filter.ts diff --git a/src/pdf/pipes/course-code-validation-pipe.ts b/src/common/pipes/models/course/course-code-validation-pipe.ts similarity index 100% rename from src/pdf/pipes/course-code-validation-pipe.ts rename to src/common/pipes/models/course/course-code-validation-pipe.ts diff --git a/src/utils/pdf/fileUtil.ts b/src/common/utils/pdf/fileUtil.ts similarity index 81% rename from src/utils/pdf/fileUtil.ts rename to src/common/utils/pdf/fileUtil.ts index 6389b89..f543d2e 100644 --- a/src/utils/pdf/fileUtil.ts +++ b/src/common/utils/pdf/fileUtil.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import fs from 'fs'; import path from 'path'; @@ -7,9 +7,11 @@ import path from 'path'; export class FileUtil { constructor(private configService: ConfigService) {} + private logger = new Logger(FileUtil.name); + public writeDataToFile(data: T, fileName: string): Promise { const pdfOutputPath = - this.configService.get('pdfOutputPath') || + this.configService.get('pdfOutputPath') ?? path.join(__dirname, fileName); const filePath = path.join(pdfOutputPath, fileName); @@ -31,12 +33,13 @@ export class FileUtil { JSON.stringify(data, urlDecodeReplacer, 2), (err) => { if (err) { - console.error('Error encountered while writing file: ', err); + this.logger.error('Error encountered while writing file: ', err); reject(err); } else { - console.log( + this.logger.log( `File "${fileName}" successfully written to "${filePath}"`, ); + resolve(filePath); } }, diff --git a/src/utils/pdf/parser/pdfParserUtil.ts b/src/common/utils/pdf/parser/pdfParserUtil.ts similarity index 100% rename from src/utils/pdf/parser/pdfParserUtil.ts rename to src/common/utils/pdf/parser/pdfParserUtil.ts diff --git a/src/utils/pdf/parser/textExtractorUtil.ts b/src/common/utils/pdf/parser/textExtractorUtil.ts similarity index 100% rename from src/utils/pdf/parser/textExtractorUtil.ts rename to src/common/utils/pdf/parser/textExtractorUtil.ts diff --git a/src/utils/url/urlUtils.ts b/src/common/utils/url/urlUtils.ts similarity index 100% rename from src/utils/url/urlUtils.ts rename to src/common/utils/url/urlUtils.ts diff --git a/src/pdf/pdf-parser/horaire/Group.ts b/src/common/website-helper/pdf/pdf-parser/horaire/Group.ts similarity index 100% rename from src/pdf/pdf-parser/horaire/Group.ts rename to src/common/website-helper/pdf/pdf-parser/horaire/Group.ts diff --git a/src/pdf/pdf-parser/horaire/HoraireCours.ts b/src/common/website-helper/pdf/pdf-parser/horaire/HoraireCours.ts similarity index 95% rename from src/pdf/pdf-parser/horaire/HoraireCours.ts rename to src/common/website-helper/pdf/pdf-parser/horaire/HoraireCours.ts index 29865a9..8ec2de9 100644 --- a/src/pdf/pdf-parser/horaire/HoraireCours.ts +++ b/src/common/website-helper/pdf/pdf-parser/horaire/HoraireCours.ts @@ -1,4 +1,4 @@ -import { CourseCodeValidationPipe } from '../../pipes/course-code-validation-pipe'; +import { CourseCodeValidationPipe } from '../../../../pipes/models/course/course-code-validation-pipe'; import { Group, IGroup } from './Group'; import { IHoraireCours } from './horaire-cours.types'; import { Period } from './Period'; diff --git a/src/pdf/pdf-parser/horaire/Period.ts b/src/common/website-helper/pdf/pdf-parser/horaire/Period.ts similarity index 100% rename from src/pdf/pdf-parser/horaire/Period.ts rename to src/common/website-helper/pdf/pdf-parser/horaire/Period.ts diff --git a/src/pdf/pdf-parser/horaire/horaire-cours.service.ts b/src/common/website-helper/pdf/pdf-parser/horaire/horaire-cours.service.ts similarity index 94% rename from src/pdf/pdf-parser/horaire/horaire-cours.service.ts rename to src/common/website-helper/pdf/pdf-parser/horaire/horaire-cours.service.ts index 8fe9aa8..facf404 100644 --- a/src/pdf/pdf-parser/horaire/horaire-cours.service.ts +++ b/src/common/website-helper/pdf/pdf-parser/horaire/horaire-cours.service.ts @@ -1,10 +1,10 @@ import { HttpService } from '@nestjs/axios'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { Output, Page, Text } from 'pdf2json'; import { firstValueFrom } from 'rxjs'; -import { PdfParserUtil } from '../../../utils/pdf/parser/pdfParserUtil'; -import { TextExtractor } from '../../../utils/pdf/parser/textExtractorUtil'; +import { PdfParserUtil } from '../../../../utils/pdf/parser/pdfParserUtil'; +import { TextExtractor } from '../../../../utils/pdf/parser/textExtractorUtil'; import { Group } from './Group'; import { HoraireCours } from './HoraireCours'; import { Period } from './Period'; @@ -16,6 +16,8 @@ export class HoraireCoursService { constructor(private httpService: HttpService) {} + private logger = new Logger(HoraireCoursService.name); + public async parsePdfFromUrl(pdfUrl: string) { try { const response = await firstValueFrom( @@ -72,8 +74,7 @@ export class HoraireCoursService { return serializedCourses; } catch (err) { - console.error('Error parsing pdf data: ' + err); - console.log(err); + this.logger.error('Error parsing pdf data: ' + err); throw new Error('Error processing PDF data: ' + err); } } diff --git a/src/pdf/pdf-parser/horaire/horaire-cours.types.ts b/src/common/website-helper/pdf/pdf-parser/horaire/horaire-cours.types.ts similarity index 100% rename from src/pdf/pdf-parser/horaire/horaire-cours.types.ts rename to src/common/website-helper/pdf/pdf-parser/horaire/horaire-cours.types.ts diff --git a/src/pdf/pdf-parser/planification/Row.ts b/src/common/website-helper/pdf/pdf-parser/planification/Row.ts similarity index 100% rename from src/pdf/pdf-parser/planification/Row.ts rename to src/common/website-helper/pdf/pdf-parser/planification/Row.ts diff --git a/src/pdf/pdf-parser/planification/planification-cours.service.ts b/src/common/website-helper/pdf/pdf-parser/planification/planification-cours.service.ts similarity index 73% rename from src/pdf/pdf-parser/planification/planification-cours.service.ts rename to src/common/website-helper/pdf/pdf-parser/planification/planification-cours.service.ts index 9bb8b65..78a85df 100644 --- a/src/pdf/pdf-parser/planification/planification-cours.service.ts +++ b/src/common/website-helper/pdf/pdf-parser/planification/planification-cours.service.ts @@ -3,10 +3,10 @@ import { Injectable } from '@nestjs/common'; import { Fill, Output, Page, Text } from 'pdf2json'; import { firstValueFrom } from 'rxjs'; -import { PdfParserUtil } from '../../../utils/pdf/parser/pdfParserUtil'; -import { TextExtractor } from '../../../utils/pdf/parser/textExtractorUtil'; -import { CourseCodeValidationPipe } from '../../pipes/course-code-validation-pipe'; -import { PlanificationCours } from './planification-cours.types'; +import { CourseCodeValidationPipe } from '../../../../pipes/models/course/course-code-validation-pipe'; +import { PdfParserUtil } from '../../../../utils/pdf/parser/pdfParserUtil'; +import { TextExtractor } from '../../../../utils/pdf/parser/textExtractorUtil'; +import { ICoursePlanification } from './planification-cours.types'; import { Row } from './Row'; @Injectable() @@ -17,7 +17,9 @@ export class PlanificationCoursService { constructor(private httpService: HttpService) {} - public async parsePdfFromUrl(pdfUrl: string): Promise { + public async parsePdfFromUrl( + pdfUrl: string, + ): Promise { try { const response = await firstValueFrom( this.httpService.get(pdfUrl, { responseType: 'arraybuffer' }), @@ -31,23 +33,23 @@ export class PlanificationCoursService { } } - private parsePlanificationCoursPdf( + public parsePlanificationCoursPdf( pdfBuffer: Buffer, pdfUrl: string, - ): Promise { + ): Promise { return PdfParserUtil.parsePdfBuffer(pdfBuffer, (pdfData) => this.processPdfData(pdfData, pdfUrl), ); } - private processPdfData( + public processPdfData( pdfData: Output, pdfUrl: string, - ): PlanificationCours[] { + ): ICoursePlanification[] { try { const headerCells: Row[] = this.parseHeaderCells(pdfData); - const courses: PlanificationCours[] = []; - let currentCourse: PlanificationCours = this.initializeCourse(); + const courses: ICoursePlanification[] = []; + let currentCourse: ICoursePlanification = this.initializeCourse(); pdfData.Pages.forEach((page: Page) => { page.Texts.forEach((textItem: Text) => { @@ -66,17 +68,18 @@ export class PlanificationCoursService { } currentCourse = this.initializeCourse(); currentCourse.code = textContent; - } else { // Process other columns - if (currentColumn && this.isSession(currentColumn.headerName)) { - // Check and add availability - if (this.isAvailability(textContent)) { - const availabilityKey = currentColumn.headerName; // Example: 'E23' - if (currentCourse.available[availabilityKey]) { - currentCourse.available[availabilityKey] += ` ${textContent}`; - } else { - currentCourse.available[availabilityKey] = textContent; - } + } else if ( + currentColumn && + this.isSession(currentColumn.headerName) + ) { + // Check and add availability + if (this.isAvailability(textContent)) { + const availabilityKey = currentColumn.headerName; // Example: 'E23' + if (currentCourse.available[availabilityKey]) { + currentCourse.available[availabilityKey] += ` ${textContent}`; + } else { + currentCourse.available[availabilityKey] = textContent; } } } @@ -96,7 +99,7 @@ export class PlanificationCoursService { } } - private initializeCourse(): PlanificationCours { + private initializeCourse(): ICoursePlanification { return { code: '', available: {}, @@ -104,7 +107,7 @@ export class PlanificationCoursService { } // Example: [ code, title, H24, E24, A24, H25, E25] - private parseHeaderCells(pdfData: { Pages: Page[] }): Row[] { + public parseHeaderCells(pdfData: { Pages: Page[] }): Row[] { const columns: Row[] = []; const headerFills = pdfData.Pages[0].Fills.filter( (fill: Fill) => fill.clr === 5, diff --git a/src/pdf/pdf-parser/planification/planification-cours.types.ts b/src/common/website-helper/pdf/pdf-parser/planification/planification-cours.types.ts similarity index 57% rename from src/pdf/pdf-parser/planification/planification-cours.types.ts rename to src/common/website-helper/pdf/pdf-parser/planification/planification-cours.types.ts index 0f92bae..08e9c58 100644 --- a/src/pdf/pdf-parser/planification/planification-cours.types.ts +++ b/src/common/website-helper/pdf/pdf-parser/planification/planification-cours.types.ts @@ -1,4 +1,4 @@ -export interface PlanificationCours { +export interface ICoursePlanification { code: string; available: Record; } diff --git a/src/pdf/pdf.controller.ts b/src/common/website-helper/pdf/pdf.controller.ts similarity index 90% rename from src/pdf/pdf.controller.ts rename to src/common/website-helper/pdf/pdf.controller.ts index 7f259f5..45ae9dd 100644 --- a/src/pdf/pdf.controller.ts +++ b/src/common/website-helper/pdf/pdf.controller.ts @@ -6,11 +6,11 @@ import { Query, } from '@nestjs/common'; -import { ERROR_MESSAGES } from '../constants/error-messages'; +import { ERROR_MESSAGES } from '../../constants/error-messages'; import { HoraireCoursService } from './pdf-parser/horaire/horaire-cours.service'; import { IHoraireCours } from './pdf-parser/horaire/horaire-cours.types'; import { PlanificationCoursService } from './pdf-parser/planification/planification-cours.service'; -import { PlanificationCours } from './pdf-parser/planification/planification-cours.types'; +import { ICoursePlanification } from './pdf-parser/planification/planification-cours.types'; @Controller('pdf') export class PdfController { @@ -46,7 +46,7 @@ export class PdfController { @Get('planification-cours') public async parsePlanificationCoursPdf( @Query('program') programCode: string, - ): Promise { + ): Promise { if (!programCode) { throw new HttpException( ERROR_MESSAGES.REQUIRED_PDF_URL, diff --git a/src/course-instance/course-instance.controller.ts b/src/course-instance/course-instance.controller.ts new file mode 100644 index 0000000..e037d73 --- /dev/null +++ b/src/course-instance/course-instance.controller.ts @@ -0,0 +1,21 @@ +import { Controller, Get, Param } from '@nestjs/common'; +import { CourseInstance } from '@prisma/client'; + +import { CourseInstanceService } from './course-instance.service'; + +@Controller('course-instances') +export class CourseInstanceController { + constructor(private readonly courseInstanceService: CourseInstanceService) {} + + @Get(':id') + public getCourseInstance( + @Param('id') id: string, + ): Promise { + return this.courseInstanceService.getCourseInstance({ id }); + } + + @Get() + public getAllCourseInstances(): Promise { + return this.courseInstanceService.getAllCourseInstances(); + } +} diff --git a/src/course-instance/course-instance.module.ts b/src/course-instance/course-instance.module.ts new file mode 100644 index 0000000..5ab71a9 --- /dev/null +++ b/src/course-instance/course-instance.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { PrismaModule } from '../prisma/prisma.module'; +import { CourseInstanceController } from './course-instance.controller'; +import { CourseInstanceService } from './course-instance.service'; + +@Module({ + imports: [PrismaModule], + controllers: [CourseInstanceController], + providers: [CourseInstanceService], +}) +export class CourseInstanceModule {} diff --git a/src/course-instance/course-instance.service.ts b/src/course-instance/course-instance.service.ts new file mode 100644 index 0000000..ee2b352 --- /dev/null +++ b/src/course-instance/course-instance.service.ts @@ -0,0 +1,99 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { CourseInstance, Prisma } from '@prisma/client'; + +import { PrismaService } from '../prisma/prisma.service'; + +@Injectable() +export class CourseInstanceService { + constructor(private readonly prisma: PrismaService) {} + + private logger = new Logger(CourseInstanceService.name); + + public getCourseInstance( + courseInstanceWhereUniqueInput: Prisma.CourseInstanceWhereUniqueInput, + ): Promise { + this.logger.log('courseInstanceById'); + + return this.prisma.courseInstance.findUnique({ + where: courseInstanceWhereUniqueInput, + }); + } + + public async getAllCourseInstances(): Promise { + this.logger.log('courseInstances'); + + const courseInstances = await this.prisma.courseInstance.findMany(); + return courseInstances; + } + + public async getCourseInstancesBySessions( + sessionIds: string[], + ): Promise { + this.logger.log('getCourseInstancesBySessions', JSON.stringify(sessionIds)); + + return this.prisma.courseInstance.findMany({ + where: { + sessionId: { + in: sessionIds, + }, + }, + }); + } + + // This will be used to get all the infos about a course instance + public async getCourseInstancesByCourse( + courseId: string, + ): Promise { + this.logger.log('getCourseInstancesByCourse', courseId); + + return this.prisma.courseInstance.findMany({ + where: { courseId }, + include: { + course: true, + }, + }); + } + + public async createCourseInstance( + data: Prisma.CourseInstanceCreateInput, + ): Promise { + this.logger.log('createCourseInstance', data); + const courseInstance = await this.prisma.courseInstance.create({ + data, + }); + return courseInstance; + } + + public async updateCourseInstance(params: { + where: Prisma.CourseInstanceWhereUniqueInput; + data: Prisma.CourseInstanceUpdateInput; + }): Promise { + this.logger.log('updateCourseInstance', params); + + const { data, where } = params; + return this.prisma.courseInstance.update({ + data, + where, + }); + } + + public async deleteCourseInstance( + where: Prisma.CourseInstanceWhereUniqueInput, + ): Promise { + this.logger.log('deleteCourseInstance', where); + + return this.prisma.courseInstance.delete({ + where, + }); + } + + public async deleteCourseInstancesBySession( + sessionId: string, + ): Promise { + this.logger.log('deleteCourseInstancesBySession', sessionId); + + return this.prisma.courseInstance.deleteMany({ + where: { sessionId }, + }); + } +} diff --git a/src/course-prerequisite/course-prerequisite.controller.ts b/src/course-prerequisite/course-prerequisite.controller.ts new file mode 100644 index 0000000..1ebf347 --- /dev/null +++ b/src/course-prerequisite/course-prerequisite.controller.ts @@ -0,0 +1,20 @@ +import { Controller, Get, Param } from '@nestjs/common'; + +import { CoursePrerequisiteService } from './course-prerequisite.service'; + +@Controller('course-prerequisites') +export class CoursePrerequisiteController { + constructor( + private readonly coursePrerequisiteService: CoursePrerequisiteService, + ) {} + + @Get(':courseId') + public async getCoursePrerequisites(@Param('courseId') courseId: string) { + return this.coursePrerequisiteService.getPrerequisites(courseId); + } + + @Get() + public async getAllCoursePrerequisites() { + return this.coursePrerequisiteService.getAllCoursePrerequisites(); + } +} diff --git a/src/course-prerequisite/course-prerequisite.module.ts b/src/course-prerequisite/course-prerequisite.module.ts new file mode 100644 index 0000000..3925edc --- /dev/null +++ b/src/course-prerequisite/course-prerequisite.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { PrismaModule } from '../prisma/prisma.module'; +import { CoursePrerequisiteController } from './course-prerequisite.controller'; +import { CoursePrerequisiteService } from './course-prerequisite.service'; + +@Module({ + imports: [PrismaModule], + controllers: [CoursePrerequisiteController], + providers: [CoursePrerequisiteService], +}) +export class CoursePrerequisiteModule {} diff --git a/src/course-prerequisite/course-prerequisite.service.ts b/src/course-prerequisite/course-prerequisite.service.ts new file mode 100644 index 0000000..b6fe33e --- /dev/null +++ b/src/course-prerequisite/course-prerequisite.service.ts @@ -0,0 +1,83 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { CoursePrerequisite, Prisma } from '@prisma/client'; + +import { PrismaService } from '../prisma/prisma.service'; + +@Injectable() +export class CoursePrerequisiteService { + constructor(private readonly prisma: PrismaService) {} + + private logger = new Logger(CoursePrerequisiteService.name); + + public async getPrerequisites(courseId: string) { + this.logger.log('coursePrerequisiteById'); + + return this.prisma.coursePrerequisite.findMany({ + where: { courseId }, + include: { prerequisite: true }, + }); + } + + public async getAllCoursePrerequisites() { + this.logger.log('getAllCoursePrerequisites'); + + return this.prisma.coursePrerequisite.findMany({ + include: { prerequisite: true }, + }); + } + + private async createCoursePrerequisite( + data: Prisma.CoursePrerequisiteCreateInput, + ): Promise { + this.logger.log('createCoursePrerequisite', data); + + const courseId = data.course.connect?.id; + const prerequisiteId = data.prerequisite.connect?.id; + + if (!courseId || !prerequisiteId) { + throw new Error('courseId and prerequisiteId must be provided.'); + } + + const existingPrerequisite = + await this.prisma.coursePrerequisite.findUnique({ + where: { + courseId_prerequisiteId: { + courseId, + prerequisiteId, + }, + }, + }); + + if (existingPrerequisite) { + return existingPrerequisite; + } + + return this.prisma.coursePrerequisite.create({ + data, + }); + } + + public async createCoursePrerequisites( + data: Prisma.CoursePrerequisiteCreateInput[], + ): Promise { + this.logger.log('ensurePrerequisitesExist', data); + + const ensuredPrerequisites = await Promise.all( + data.map((prerequisiteData) => + this.createCoursePrerequisite(prerequisiteData), + ), + ); + + return ensuredPrerequisites; + } + + public async deleteCoursePrerequisite( + where: Prisma.CoursePrerequisiteWhereUniqueInput, + ): Promise { + this.logger.log('deleteCoursePrerequisite', where); + + return this.prisma.coursePrerequisite.delete({ + where, + }); + } +} diff --git a/src/course/course.controller.ts b/src/course/course.controller.ts new file mode 100644 index 0000000..b0dc1eb --- /dev/null +++ b/src/course/course.controller.ts @@ -0,0 +1,18 @@ +import { Controller, Get, Param } from '@nestjs/common'; + +import { CourseService } from './course.service'; + +@Controller('courses') +export class CourseController { + constructor(private readonly courseService: CourseService) {} + + @Get(':id') + public getCourse(@Param('id') id: string) { + return this.courseService.getCourse({ id }); + } + + @Get() + public getAllCourses() { + return this.courseService.getAllCourses(); + } +} diff --git a/src/course/course.module.ts b/src/course/course.module.ts new file mode 100644 index 0000000..35c6d1c --- /dev/null +++ b/src/course/course.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { PrismaModule } from '../prisma/prisma.module'; +import { CourseController } from './course.controller'; +import { CourseService } from './course.service'; + +@Module({ + imports: [PrismaModule], + controllers: [CourseController], + providers: [CourseService], +}) +export class CourseModule {} diff --git a/src/course/course.service.ts b/src/course/course.service.ts new file mode 100644 index 0000000..cae3536 --- /dev/null +++ b/src/course/course.service.ts @@ -0,0 +1,128 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Course, Prisma, Session } from '@prisma/client'; + +import { PrismaService } from '../prisma/prisma.service'; + +@Injectable() +export class CourseService { + constructor(private readonly prisma: PrismaService) {} + + private logger = new Logger(CourseService.name); + + public async getCourse( + courseWhereUniqueInput: Prisma.CourseWhereUniqueInput, + ): Promise { + this.logger.log('courseById', courseWhereUniqueInput); + + const course = await this.prisma.course.findUnique({ + where: courseWhereUniqueInput, + }); + + return course; + } + + public async getAllCourses() { + this.logger.log('getAllCourses'); + + return this.prisma.course.findMany(); + } + + public async getCoursesByProgram(programId: string): Promise { + this.logger.log('getCoursesByProgram', programId); + + return this.prisma.course.findMany({ + where: { + programs: { + some: { + programId, + }, + }, + }, + }); + } + + public async getCourseAvailability( + courseId: string, + ): Promise<{ session: Session; available: boolean }[]> { + this.logger.log('getCourseAvailability', courseId); + + const courseInstances = await this.prisma.courseInstance.findMany({ + where: { courseId }, + include: { + session: true, + }, + }); + + const sessionAvailability = courseInstances.map((instance) => ({ + session: instance.session, + available: true, + })); + + return sessionAvailability; + } + + public async createCourse(data: Prisma.CourseCreateInput): Promise { + this.logger.log('createCourse', data); + + const course = await this.prisma.course.create({ + data, + }); + + return course; + } + + public async updateCourse(params: { + where: Prisma.CourseWhereUniqueInput; + data: Prisma.CourseUpdateInput; + }): Promise { + this.logger.log('updateCourse', params); + + const { data, where } = params; + return this.prisma.course.update({ + data, + where, + }); + } + + private async upsertCourse( + courseData: Prisma.CourseCreateInput, + ): Promise { + const existingCourse = await this.prisma.course.findUnique({ + where: { id: courseData.id }, + }); + + if (existingCourse) { + if (JSON.stringify(existingCourse) !== JSON.stringify(courseData)) { + return this.updateCourse({ + where: { id: courseData.id }, + data: courseData, + }); + } + + return existingCourse; + } + return this.createCourse(courseData); + } + + public async upsertCourses( + data: Prisma.CourseCreateInput[], + ): Promise { + this.logger.log('upsertCourses', data); + + const upsertedCourses = await Promise.all( + data.map((courseData) => this.upsertCourse(courseData)), + ); + + return upsertedCourses; + } + + public async deleteCourse( + where: Prisma.CourseWhereUniqueInput, + ): Promise { + this.logger.log('deleteCourse', where); + + return this.prisma.course.delete({ + where, + }); + } +} diff --git a/src/main.ts b/src/main.ts index d9b4fc9..7cb027e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,7 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; -import { HttpExceptionFilter } from './http-exception.filter'; +import { HttpExceptionFilter } from './common/exceptions/http-exception.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule); diff --git a/src/prisma/prisma.module.ts b/src/prisma/prisma.module.ts new file mode 100644 index 0000000..b38960e --- /dev/null +++ b/src/prisma/prisma.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; + +import { PrismaService } from './prisma.service'; + +@Module({ + imports: [], + controllers: [], + providers: [PrismaService], + exports: [PrismaService], +}) +export class PrismaModule {} diff --git a/src/prisma/prisma.service.ts b/src/prisma/prisma.service.ts new file mode 100644 index 0000000..275dfca --- /dev/null +++ b/src/prisma/prisma.service.ts @@ -0,0 +1,16 @@ +import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; +import { PrismaClient } from '@prisma/client'; + +@Injectable() +export class PrismaService + extends PrismaClient + implements OnModuleInit, OnModuleDestroy +{ + public async onModuleInit() { + await this.$connect(); + } + + public async onModuleDestroy() { + await this.$disconnect(); + } +} diff --git a/src/program/program.controller.ts b/src/program/program.controller.ts new file mode 100644 index 0000000..bb35b3a --- /dev/null +++ b/src/program/program.controller.ts @@ -0,0 +1,27 @@ +import { + Controller, + Get, + Param, + UsePipes, + ValidationPipe, +} from '@nestjs/common'; +import { Program } from '@prisma/client'; + +import { UuidDto } from '../common/exceptions/dtos/uuid.dto'; +import { ProgramService } from './program.service'; + +@Controller('programs') +export class ProgramController { + constructor(private readonly programService: ProgramService) {} + + @Get(':id') + @UsePipes(new ValidationPipe({ transform: true })) + public async getProgram(@Param() { id }: UuidDto): Promise { + return this.programService.getProgram({ id }); + } + + @Get() + public async getAllPrograms(): Promise { + return this.programService.getAllPrograms(); + } +} diff --git a/src/program/program.module.ts b/src/program/program.module.ts new file mode 100644 index 0000000..3e6cd69 --- /dev/null +++ b/src/program/program.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { PrismaModule } from '../prisma/prisma.module'; +import { ProgramController } from './program.controller'; +import { ProgramService } from './program.service'; + +@Module({ + imports: [PrismaModule], + controllers: [ProgramController], + providers: [ProgramService], +}) +export class ProgramModule {} diff --git a/src/program/program.service.ts b/src/program/program.service.ts new file mode 100644 index 0000000..9e4d4d5 --- /dev/null +++ b/src/program/program.service.ts @@ -0,0 +1,96 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Prisma, Program, ProgramType } from '@prisma/client'; + +import { PrismaService } from '../prisma/prisma.service'; + +@Injectable() +export class ProgramService { + constructor(private readonly prisma: PrismaService) {} + + private logger = new Logger(ProgramService.name); + + public async getProgram( + programWhereUniqueInput: Prisma.ProgramWhereUniqueInput, + ): Promise { + this.logger.log('getProgram', programWhereUniqueInput); + + return this.prisma.program.findUnique({ + where: programWhereUniqueInput, + }); + } + + public async getAllPrograms(): Promise { + this.logger.log('getAllPrograms'); + + return this.prisma.program.findMany(); + } + + public async createProgram( + data: Prisma.ProgramCreateInput, + ): Promise { + this.logger.log('createProgram', data); + + return this.prisma.program.create({ + data: { + ...data, + programTypeIds: data.programTypeIds ?? '[]', + }, + }); + } + + public async upsertProgram( + data: Prisma.ProgramCreateInput, + ): Promise { + this.logger.log('upsertProgram', data); + + return this.prisma.program.upsert({ + where: { id: data.id }, + update: { + ...data, + updatedAt: new Date(), + programTypeIds: data.programTypeIds ?? '[]', + }, + create: { + ...data, + createdAt: new Date(), + updatedAt: new Date(), + programTypeIds: data.programTypeIds ?? '[]', + }, + }); + } + + public async upsertPrograms( + data: Prisma.ProgramCreateInput[], + ): Promise { + this.logger.log('upsertPrograms', data); + return Promise.all( + data.map((programData) => this.upsertProgram(programData)), + ); + } + + public async createProgramTypes(types: ProgramType[]): Promise { + this.logger.log('createProgramTypes', types); + + await Promise.all( + types.map((type) => + this.prisma.programType.upsert({ + where: { id: type.id }, + update: { title: type.title }, + create: { + id: type.id, + title: type.title, + }, + }), + ), + ); + } + + public async deleteProgram( + where: Prisma.ProgramWhereUniqueInput, + ): Promise { + this.logger.log('deleteProgram', JSON.stringify(where)); + return this.prisma.program.delete({ + where, + }); + } +} diff --git a/src/session/session.controller.ts b/src/session/session.controller.ts new file mode 100644 index 0000000..66813f5 --- /dev/null +++ b/src/session/session.controller.ts @@ -0,0 +1,27 @@ +import { + Controller, + Get, + Param, + UsePipes, + ValidationPipe, +} from '@nestjs/common'; +import { Session } from '@prisma/client'; + +import { UuidDto } from '../common/exceptions/dtos/uuid.dto'; +import { SessionService } from './session.service'; + +@Controller('sessions') +export class SessionController { + constructor(private readonly sessionService: SessionService) {} + + @Get(':id') + @UsePipes(new ValidationPipe({ transform: true })) + public async getSession(@Param() { id }: UuidDto): Promise { + return this.sessionService.getSession(id); + } + + @Get() + public async getAllSessions(): Promise { + return this.sessionService.getAllSessions(); + } +} diff --git a/src/session/session.module.ts b/src/session/session.module.ts new file mode 100644 index 0000000..e429ff6 --- /dev/null +++ b/src/session/session.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { PrismaModule } from '../prisma/prisma.module'; +import { SessionController } from './session.controller'; +import { SessionService } from './session.service'; + +@Module({ + imports: [PrismaModule], + controllers: [SessionController], + providers: [SessionService], +}) +export class SessionModule {} diff --git a/src/session/session.service.ts b/src/session/session.service.ts new file mode 100644 index 0000000..74abd42 --- /dev/null +++ b/src/session/session.service.ts @@ -0,0 +1,60 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Prisma, Session, Trimester } from '@prisma/client'; + +import { PrismaService } from '../prisma/prisma.service'; + +@Injectable() +export class SessionService { + constructor(private readonly prisma: PrismaService) {} + + private logger = new Logger(SessionService.name); + + public async getSession(id: string): Promise { + this.logger.log('getSession', id); + + return this.prisma.session.findUnique({ + where: { id }, + }); + } + + public async getAllSessions(): Promise { + return this.prisma.session.findMany(); + } + + public async createSession( + data: Prisma.SessionCreateInput, + ): Promise { + return this.prisma.session.create({ + data, + }); + } + + public async upsertSession( + id: string, + data: Prisma.SessionUpdateInput, + ): Promise { + const createSessionDto: Prisma.SessionCreateInput = { + ...data, + id, + trimester: data.trimester as Trimester, + year: data.year as number, + createdAt: new Date(), + updatedAt: new Date(), + }; + + return this.prisma.session.upsert({ + where: { id }, + update: { + ...data, + updatedAt: new Date(), + }, + create: createSessionDto, + }); + } + + public async removeSession(id: string): Promise { + return this.prisma.session.delete({ + where: { id }, + }); + } +} diff --git a/test/common/api-helper/ets/course/ets-course.service.spec.ts b/test/common/api-helper/ets/course/ets-course.service.spec.ts new file mode 100644 index 0000000..b26bfbe --- /dev/null +++ b/test/common/api-helper/ets/course/ets-course.service.spec.ts @@ -0,0 +1,84 @@ +import { HttpService } from '@nestjs/axios'; +import { Test, TestingModule } from '@nestjs/testing'; +import { AxiosResponse } from 'axios'; +import { of } from 'rxjs'; + +import { + EtsCourseService, + IEtsCourse, + IEtsCoursesData, +} from '../../../../../src/common/api-helper/ets/course/ets-course.service'; + +describe('EtsCourseService', () => { + let service: EtsCourseService; + let httpService: HttpService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + EtsCourseService, + { + provide: HttpService, + useValue: { + get: jest.fn(), + }, + }, + ], + }).compile(); + + service = module.get(EtsCourseService); + httpService = module.get(HttpService); + }); + + it('should fetch all courses', async () => { + const mockCourses: IEtsCoursesData[] = [ + { id: 1, title: 'Course 1', code: 'C1', cycle: 'Cycle 1' }, + { id: 2, title: 'Course 2', code: 'C2', cycle: 'Cycle 2' }, + ]; + + const mockResponse: AxiosResponse<{ results: IEtsCoursesData[] }> = { + data: { results: mockCourses }, + status: 200, + statusText: 'OK', + headers: {}, + config: { + headers: { + get: () => 'application/json', + set: () => {}, + has: () => true, + delete: () => true, + }, + } as never, + }; + jest.spyOn(httpService, 'get').mockReturnValue(of(mockResponse)); + + const result = await service.fetchAllCourses(); + expect(result).toEqual(mockCourses); + }); + + it('should fetch courses by ids', async () => { + const mockCourses: IEtsCourse[] = [ + { id: 1, title: 'Course 1', code: 'C1', cycle: 'Cycle 1', credits: '3' }, + { id: 2, title: 'Course 2', code: 'C2', cycle: 'Cycle 2', credits: '4' }, + ]; + + const mockResponse: AxiosResponse = { + data: mockCourses, + status: 200, + statusText: 'OK', + headers: {}, + config: { + headers: { + get: () => 'application/json', + set: () => {}, + has: () => true, + delete: () => true, + }, + } as never, + }; + jest.spyOn(httpService, 'get').mockReturnValue(of(mockResponse)); + + const result = await service.fetchCoursesById('1,2'); + expect(result).toEqual(mockCourses); + }); +}); diff --git a/test/common/website-helper/pdf/pdf-parser/planification/planification-cours.service.test.ts b/test/common/website-helper/pdf/pdf-parser/planification/planification-cours.service.test.ts new file mode 100644 index 0000000..009bcd3 --- /dev/null +++ b/test/common/website-helper/pdf/pdf-parser/planification/planification-cours.service.test.ts @@ -0,0 +1,56 @@ +import { HttpService } from '@nestjs/axios'; +import { Test, TestingModule } from '@nestjs/testing'; +import { AxiosResponse } from 'axios'; +import { of } from 'rxjs'; + +import { PlanificationCoursService } from '../../../../../../src/common/website-helper/pdf/pdf-parser/planification/planification-cours.service'; + +jest.mock('@nestjs/axios'); +jest.mock( + '../../../../../../src/common/pipes/models/course/course-code-validation-pipe', +); +jest.mock('../../../../../../src/common/utils/pdf/parser/pdfParserUtil'); +jest.mock('../../../../../../src/common/utils/pdf/parser/textExtractorUtil'); + +describe('PlanificationCoursService', () => { + let service: PlanificationCoursService; + let httpService: HttpService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PlanificationCoursService, HttpService], + }).compile(); + + service = module.get(PlanificationCoursService); + httpService = module.get(HttpService); + }); + + describe('parsePdfFromUrl', () => { + it('should fetch and parse the PDF', async () => { + const pdfUrl = + 'https://horaire.etsmtl.ca/Horairepublication/Planification-7084.pdf'; + const pdfBuffer = Buffer.from('sample pdf data'); + const response: AxiosResponse = { + data: pdfBuffer, + status: 200, + statusText: 'OK', + headers: {} as never, + config: { headers: {} as never }, + }; + + jest.spyOn(httpService, 'get').mockReturnValue(of(response)); + jest.spyOn(service, 'parsePlanificationCoursPdf').mockResolvedValue([]); + + const result = await service.parsePdfFromUrl(pdfUrl); + + expect(httpService.get).toHaveBeenCalledWith(pdfUrl, { + responseType: 'arraybuffer', + }); + expect(service.parsePlanificationCoursPdf).toHaveBeenCalledWith( + pdfBuffer, + pdfUrl, + ); + expect(result).toEqual([]); + }); + }); +}); diff --git a/test/course-instance/course-instance.controller.spec.ts b/test/course-instance/course-instance.controller.spec.ts new file mode 100644 index 0000000..e1207ff --- /dev/null +++ b/test/course-instance/course-instance.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { CourseInstanceController } from '../../src/course-instance/course-instance.controller'; +import { CourseInstanceService } from '../../src/course-instance/course-instance.service'; +import { PrismaService } from '../../src/prisma/prisma.service'; + +describe('CourseInstanceController', () => { + let controller: CourseInstanceController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [CourseInstanceController], + providers: [PrismaService, CourseInstanceService], + }).compile(); + + controller = module.get(CourseInstanceController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/test/course-instance/course-instance.service.spec.ts b/test/course-instance/course-instance.service.spec.ts new file mode 100644 index 0000000..84ae409 --- /dev/null +++ b/test/course-instance/course-instance.service.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { CourseInstanceService } from '../../src/course-instance/course-instance.service'; +import { PrismaService } from '../../src/prisma/prisma.service'; + +describe('CourseInstanceService', () => { + let service: CourseInstanceService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [CourseInstanceService, PrismaService], + }).compile(); + + service = module.get(CourseInstanceService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/test/course-prerequisite/course-prerequisite.controller.spec.ts b/test/course-prerequisite/course-prerequisite.controller.spec.ts new file mode 100644 index 0000000..da1731c --- /dev/null +++ b/test/course-prerequisite/course-prerequisite.controller.spec.ts @@ -0,0 +1,35 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { CoursePrerequisiteController } from '../../src/course-prerequisite/course-prerequisite.controller'; +import { CoursePrerequisiteService } from '../../src/course-prerequisite/course-prerequisite.service'; +import { PrismaService } from '../../src/prisma/prisma.service'; + +describe('CoursePrerequisiteController', () => { + let controller: CoursePrerequisiteController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [CoursePrerequisiteController], + providers: [ + CoursePrerequisiteService, + { + provide: PrismaService, + useValue: { + coursePrerequisite: { + findMany: jest.fn(), + findUnique: jest.fn(), + }, + }, + }, + ], + }).compile(); + + controller = module.get( + CoursePrerequisiteController, + ); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/test/course-prerequisite/course-prerequisite.service.spec.ts b/test/course-prerequisite/course-prerequisite.service.spec.ts new file mode 100644 index 0000000..08f9c00 --- /dev/null +++ b/test/course-prerequisite/course-prerequisite.service.spec.ts @@ -0,0 +1,34 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { CoursePrerequisiteService } from '../../src/course-prerequisite/course-prerequisite.service'; +import { PrismaService } from '../../src/prisma/prisma.service'; + +describe('CoursePrerequisiteService', () => { + let service: CoursePrerequisiteService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + CoursePrerequisiteService, + { + provide: PrismaService, + useValue: { + coursePrerequisite: { + findMany: jest.fn(), + findUnique: jest.fn(), + create: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + }, + }, + }, + ], + }).compile(); + + service = module.get(CoursePrerequisiteService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/test/course/course.controller.spec.ts b/test/course/course.controller.spec.ts new file mode 100644 index 0000000..557ce1b --- /dev/null +++ b/test/course/course.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { CourseController } from '../../src/course/course.controller'; +import { CourseService } from '../../src/course/course.service'; +import { PrismaService } from '../../src/prisma/prisma.service'; + +describe('CourseController', () => { + let controller: CourseController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [CourseController], + providers: [PrismaService, CourseService], + }).compile(); + + controller = module.get(CourseController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/test/course/course.service.spec.ts b/test/course/course.service.spec.ts new file mode 100644 index 0000000..7bc86de --- /dev/null +++ b/test/course/course.service.spec.ts @@ -0,0 +1,85 @@ +import { INestApplication, ValidationPipe } from '@nestjs/common'; +import { Test, TestingModule } from '@nestjs/testing'; +import { Course, Session } from '@prisma/client'; +import { useContainer } from 'class-validator'; +import * as request from 'supertest'; + +import { AppModule } from '../../src/app.module'; +import { PrismaService } from '../../src/prisma/prisma.service'; + +describe('CourseService (e2e)', () => { + let app: INestApplication; + let prisma: PrismaService; + let course: Course; + let session: Session; + + const courseShape = expect.objectContaining({ + id: expect.any(String), + programId: expect.any(String), + code: expect.any(String), + title: expect.any(String), + description: expect.any(String), + credits: expect.any(Number), + }); + + beforeAll(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + prisma = app.get(PrismaService); + + useContainer(app.select(AppModule), { fallbackOnErrors: true }); + app.useGlobalPipes(new ValidationPipe({ whitelist: true })); + + await app.init(); + + session = await prisma.session.create({ + data: { + trimester: 'A', + year: 2021, + }, + }); + + course = await prisma.course.create({ + data: { + id: '1', + programId: '1', + code: 'CS101', + title: 'Introduction to Computer Science', + description: 'A basic course on computer science', + credits: 3, + }, + }); + }); + + afterAll(async () => { + await prisma.course.deleteMany(); + await prisma.session.deleteMany(); + await prisma.$disconnect(); + await app.close(); + }); + + describe('GET /courses', () => { + it('returns a list of courses', async () => { + const { status, body } = await request(app.getHttpServer()).get( + '/courses', + ); + + expect(status).toBe(200); + expect(body).toStrictEqual(expect.arrayContaining([courseShape])); + }); + }); + + describe('GET /courses/:id', () => { + it('returns a course', async () => { + const { status, body } = await request(app.getHttpServer()).get( + `/courses/${course.id}`, + ); + + expect(status).toBe(200); + expect(body).toStrictEqual(courseShape); + }); + }); +}); diff --git a/test/program/program.controller.spec.ts b/test/program/program.controller.spec.ts new file mode 100644 index 0000000..4120ce6 --- /dev/null +++ b/test/program/program.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { PrismaService } from '../../src/prisma/prisma.service'; +import { ProgramController } from '../../src/program/program.controller'; +import { ProgramService } from '../../src/program/program.service'; + +describe('ProgramController', () => { + let controller: ProgramController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [ProgramController], + providers: [PrismaService, ProgramService], + }).compile(); + + controller = module.get(ProgramController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/test/program/program.service.spec.ts b/test/program/program.service.spec.ts new file mode 100644 index 0000000..717b438 --- /dev/null +++ b/test/program/program.service.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { PrismaService } from '../../src/prisma/prisma.service'; +import { ProgramService } from '../../src/program/program.service'; + +describe('ProgramService', () => { + let service: ProgramService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PrismaService, ProgramService], + }).compile(); + + service = module.get(ProgramService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/test/session/session.controller.spec.ts b/test/session/session.controller.spec.ts new file mode 100644 index 0000000..2358a37 --- /dev/null +++ b/test/session/session.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { PrismaService } from '../../src/prisma/prisma.service'; +import { SessionController } from '../../src/session/session.controller'; +import { SessionService } from '../../src/session/session.service'; + +describe('SessionController', () => { + let controller: SessionController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [SessionController], + providers: [PrismaService, SessionService], + }).compile(); + + controller = module.get(SessionController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/test/session/session.service.spec.ts b/test/session/session.service.spec.ts new file mode 100644 index 0000000..386a45e --- /dev/null +++ b/test/session/session.service.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { PrismaService } from '../../src/prisma/prisma.service'; +import { SessionService } from '../../src/session/session.service'; + +describe('SessionService', () => { + let service: SessionService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PrismaService, SessionService], + }).compile(); + + service = module.get(SessionService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index e605c69..22ba488 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,6 @@ "incremental": true, "strict": true, "strictBindCallApply": false, - "typeRoots": ["node_modules/@types"], + "typeRoots": ["node_modules/@types"] } } diff --git a/yarn.lock b/yarn.lock index cddfb0d..dad770e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -338,6 +338,11 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@braintree/sanitize-url@^6.0.1": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" + integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -681,6 +686,16 @@ resolved "https://registry.yarnpkg.com/@lukeed/csprng/-/csprng-1.1.0.tgz#1e3e4bd05c1cc7a0b2ddbd8a03f39f6e4b5e6cfe" integrity sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA== +"@mermaid-js/mermaid-cli@^10.6.1": + version "10.9.1" + resolved "https://registry.yarnpkg.com/@mermaid-js/mermaid-cli/-/mermaid-cli-10.9.1.tgz#9ccd0a9fdb09275817617665ee5432d352c838cc" + integrity sha512-ajpGUKmB5YbRRzrFR+0dbykF9mTvce4FpHWGYPYTry8ZsOgP6h7SUnojyCJDGgbReCnArODCM8L212qIcxshIw== + dependencies: + chalk "^5.0.1" + commander "^10.0.0" + mermaid "^10.8.0" + puppeteer "^19.0.0" + "@mole-inc/bin-wrapper@^8.0.1": version "8.0.1" resolved "https://registry.yarnpkg.com/@mole-inc/bin-wrapper/-/bin-wrapper-8.0.1.tgz#d7fd0ceb1cfa8a855293a3ed9d7d135f4d442f0e" @@ -759,6 +774,11 @@ path-to-regexp "3.2.0" tslib "2.6.2" +"@nestjs/mapped-types@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz#485d6b44e19779c98d04e52bd1d2bcc7001df0ea" + integrity sha512-bSJv4pd6EY99NX9CjBIyn4TVDoSit82DUZlL4I3bqNfy5Gt+gXTa86i3I/i0iIV9P4hntcGM5GyO+FhZAhxtyg== + "@nestjs/platform-express@^10.0.0": version "10.3.7" resolved "https://registry.yarnpkg.com/@nestjs/platform-express/-/platform-express-10.3.7.tgz#ae3fc59609bdc0ffc5029a6e74d59a5d1e257eef" @@ -828,46 +848,72 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@prisma/client@^5.7.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.12.1.tgz#c26a674fea76754b3a9e8b90a11e617f90212f76" - integrity sha512-6/JnizEdlSBxDIdiLbrBdMW5NqDxOmhXAJaNXiPpgzAPr/nLZResT6MMpbOHLo5yAbQ1Vv5UU8PTPRzb0WIxdA== - -"@prisma/debug@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.12.1.tgz#007c8ad2e466d565bcd0671b8846c27f8700c722" - integrity sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A== - -"@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab": - version "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab.tgz#c78d099a3fe86d446db7442e64e56987e39e7f32" - integrity sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g== - -"@prisma/engines@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.12.1.tgz#a50649427d627a9af962a188a84c65d61c6e2b3f" - integrity sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA== - dependencies: - "@prisma/debug" "5.12.1" - "@prisma/engines-version" "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab" - "@prisma/fetch-engine" "5.12.1" - "@prisma/get-platform" "5.12.1" - -"@prisma/fetch-engine@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.12.1.tgz#c38e9fa17fdc535b4c83cbb7645569ad0a511fa9" - integrity sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA== - dependencies: - "@prisma/debug" "5.12.1" - "@prisma/engines-version" "5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab" - "@prisma/get-platform" "5.12.1" - -"@prisma/get-platform@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.12.1.tgz#33f427f6d744dee62a9e06858889691d78b50804" - integrity sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ== - dependencies: - "@prisma/debug" "5.12.1" +"@prisma/client@^5.15.0": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.15.1.tgz#68e1f8b092a0eed6cd61d5f94ed8bb5cc3bc8ca1" + integrity sha512-fmZRGmsUJ9+VwC/AvfP/PwdpD0xAEyPvNsD9/B3+GYpETq9VejVRT3PiqNvl76q1uYYzNZeo8u/LmzzTetHSEg== + +"@prisma/debug@5.15.0": + version "5.15.0" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.15.0.tgz#a4c1d8dbca9cf29aab1c82a56a65224ed3e05f13" + integrity sha512-QpEAOjieLPc/4sMny/WrWqtpIAmBYsgqwWlWwIctqZO0AbhQ9QcT6x2Ut3ojbDo/pFRCCA1Z1+xm2MUy7fAkZA== + +"@prisma/debug@5.17.0": + version "5.17.0" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.17.0.tgz#a765105848993984535b6066f8ebc6e6ead26533" + integrity sha512-l7+AteR3P8FXiYyo496zkuoiJ5r9jLQEdUuxIxNCN1ud8rdbH3GTxm+f+dCyaSv9l9WY+29L9czaVRXz9mULfg== + +"@prisma/engines-version@5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022": + version "5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022.tgz#4469a372b74088db05c0fc8cff65f229b804fa51" + integrity sha512-3BEgZ41Qb4oWHz9kZNofToRvNeS4LZYaT9pienR1gWkjhky6t6K1NyeWNBkqSj2llgraUNbgMOCQPY4f7Qp5wA== + +"@prisma/engines@5.15.0": + version "5.15.0" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.15.0.tgz#bddf1973b5b0d2ebed473ed445b1a7c8dd23300b" + integrity sha512-hXL5Sn9hh/ZpRKWiyPA5GbvF3laqBHKt6Vo70hYqqOhh5e0ZXDzHcdmxNvOefEFeqxra2DMz2hNbFoPvqrVe1w== + dependencies: + "@prisma/debug" "5.15.0" + "@prisma/engines-version" "5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022" + "@prisma/fetch-engine" "5.15.0" + "@prisma/get-platform" "5.15.0" + +"@prisma/fetch-engine@5.15.0": + version "5.15.0" + resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.15.0.tgz#f5bafd6aed3f58c41b5d0d6f832d652aa5d4cde7" + integrity sha512-z6AY5yyXxc20Klj7wwnfGP0iIUkVKzybqapT02zLYR/nf9ynaeN8bq73WRmi1TkLYn+DJ5Qy+JGu7hBf1pE78A== + dependencies: + "@prisma/debug" "5.15.0" + "@prisma/engines-version" "5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022" + "@prisma/get-platform" "5.15.0" + +"@prisma/generator-helper@^4.0.0 || ^5.0.0": + version "5.17.0" + resolved "https://registry.yarnpkg.com/@prisma/generator-helper/-/generator-helper-5.17.0.tgz#e499b748f77225f4bf78ad3694a5c58a5ece27bd" + integrity sha512-UcYpNjjQNVHAjIxgjfXnF4fcKU7B2vuzG1L27xIV81xQoGSbxg7v670URBhd0/ZoE8v2Itj2bbuyezY1ViHVaA== + dependencies: + "@prisma/debug" "5.17.0" + +"@prisma/get-platform@5.15.0": + version "5.15.0" + resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.15.0.tgz#d39fbe8458432f76afeb6c9199bffae73db4f5cc" + integrity sha512-1GULDkW4+/VQb73vihxCBSc4Chc2x88MA+O40tcZFjmBzG4/fF44PaXFxUqKSFltxU9L9GIMLhh0Gfkk/pUbtg== + dependencies: + "@prisma/debug" "5.15.0" + +"@puppeteer/browsers@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-0.5.0.tgz#1a1ee454b84a986b937ca2d93146f25a3fe8b670" + integrity sha512-Uw6oB7VvmPRLE4iKsjuOh8zgDabhNX67dzo8U/BB0f9527qx+4eeUs+korU98OhG5C4ubg7ufBgVi63XYwS6TQ== + dependencies: + debug "4.3.4" + extract-zip "2.0.1" + https-proxy-agent "5.0.1" + progress "2.0.3" + proxy-from-env "1.1.0" + tar-fs "2.1.1" + unbzip2-stream "1.4.3" + yargs "17.7.1" "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -1082,6 +1128,30 @@ resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.5.tgz#14a3e83fa641beb169a2dd8422d91c3c345a9a78" integrity sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q== +"@types/d3-scale-chromatic@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644" + integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw== + +"@types/d3-scale@^4.0.3": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" + integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-time@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" + integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + +"@types/debug@^4.0.0": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== + dependencies: + "@types/ms" "*" + "@types/eslint-scope@^3.7.3": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" @@ -1184,6 +1254,13 @@ dependencies: "@types/node" "*" +"@types/mdast@^3.0.0": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" + integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== + dependencies: + "@types/unist" "^2" + "@types/methods@^1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547" @@ -1194,6 +1271,11 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== +"@types/ms@*": + version "0.7.34" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" + integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== + "@types/multer@^1.4.11": version "1.4.11" resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.11.tgz#c70792670513b4af1159a2b60bf48cc932af55c5" @@ -1268,6 +1350,11 @@ dependencies: "@types/superagent" "*" +"@types/unist@^2", "@types/unist@^2.0.0": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" + integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== + "@types/validator@^13.11.8": version "13.11.9" resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.11.9.tgz#adfe96520b437a0eaa798a475877bf2f75ee402d" @@ -1285,7 +1372,14 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@7.6.0", "@typescript-eslint/eslint-plugin@^7.5.0": +"@types/yauzl@^2.9.1": + version "2.10.3" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999" + integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q== + dependencies: + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz#1f5df5cda490a0bcb6fbdd3382e19f1241024242" integrity sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A== @@ -1302,7 +1396,22 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/parser@7.6.0", "@typescript-eslint/parser@^7.5.0": +"@typescript-eslint/eslint-plugin@^7.5.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz#3cdeb5d44d051b21a9567535dd90702b2a42c6ff" + integrity sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "7.13.0" + "@typescript-eslint/type-utils" "7.13.0" + "@typescript-eslint/utils" "7.13.0" + "@typescript-eslint/visitor-keys" "7.13.0" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/parser@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.6.0.tgz#0aca5de3045d68b36e88903d15addaf13d040a95" integrity sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg== @@ -1324,6 +1433,17 @@ "@typescript-eslint/visitor-keys" "6.21.0" debug "^4.3.4" +"@typescript-eslint/parser@^7.5.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.13.0.tgz#9489098d68d57ad392f507495f2b82ce8b8f0a6b" + integrity sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA== + dependencies: + "@typescript-eslint/scope-manager" "7.13.0" + "@typescript-eslint/types" "7.13.0" + "@typescript-eslint/typescript-estree" "7.13.0" + "@typescript-eslint/visitor-keys" "7.13.0" + debug "^4.3.4" + "@typescript-eslint/scope-manager@6.21.0": version "6.21.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" @@ -1332,6 +1452,14 @@ "@typescript-eslint/types" "6.21.0" "@typescript-eslint/visitor-keys" "6.21.0" +"@typescript-eslint/scope-manager@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz#6927d6451537ce648c6af67a2327378d4cc18462" + integrity sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng== + dependencies: + "@typescript-eslint/types" "7.13.0" + "@typescript-eslint/visitor-keys" "7.13.0" + "@typescript-eslint/scope-manager@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz#1e9972f654210bd7500b31feadb61a233f5b5e9d" @@ -1340,6 +1468,16 @@ "@typescript-eslint/types" "7.6.0" "@typescript-eslint/visitor-keys" "7.6.0" +"@typescript-eslint/type-utils@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.13.0.tgz#4587282b5227a23753ea8b233805ecafc3924c76" + integrity sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A== + dependencies: + "@typescript-eslint/typescript-estree" "7.13.0" + "@typescript-eslint/utils" "7.13.0" + debug "^4.3.4" + ts-api-utils "^1.3.0" + "@typescript-eslint/type-utils@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz#644f75075f379827d25fe0713e252ccd4e4a428c" @@ -1355,6 +1493,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== +"@typescript-eslint/types@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.13.0.tgz#0cca95edf1f1fdb0cfe1bb875e121b49617477c5" + integrity sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA== + "@typescript-eslint/types@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.6.0.tgz#53dba7c30c87e5f10a731054266dd905f1fbae38" @@ -1374,6 +1517,20 @@ semver "^7.5.4" ts-api-utils "^1.0.1" +"@typescript-eslint/typescript-estree@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz#4cc24fc155088ebf3b3adbad62c7e60f72c6de1c" + integrity sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw== + dependencies: + "@typescript-eslint/types" "7.13.0" + "@typescript-eslint/visitor-keys" "7.13.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + "@typescript-eslint/typescript-estree@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz#112a3775563799fd3f011890ac8322f80830ac17" @@ -1388,6 +1545,16 @@ semver "^7.6.0" ts-api-utils "^1.3.0" +"@typescript-eslint/utils@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.13.0.tgz#f84e7e8aeceae945a9a3f40d077fd95915308004" + integrity sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "7.13.0" + "@typescript-eslint/types" "7.13.0" + "@typescript-eslint/typescript-estree" "7.13.0" + "@typescript-eslint/utils@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.6.0.tgz#e400d782280b6f724c8a1204269d984c79202282" @@ -1409,6 +1576,14 @@ "@typescript-eslint/types" "6.21.0" eslint-visitor-keys "^3.4.1" +"@typescript-eslint/visitor-keys@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz#2eb7ce8eb38c2b0d4a494d1fe1908e7071a1a353" + integrity sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw== + dependencies: + "@typescript-eslint/types" "7.13.0" + eslint-visitor-keys "^3.4.3" + "@typescript-eslint/visitor-keys@7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz#d1ce13145844379021e1f9bd102c1d78946f4e76" @@ -1586,6 +1761,13 @@ acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + ajv-formats@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -1916,7 +2098,7 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -bl@^4.1.0: +bl@^4.0.3, bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== @@ -1989,12 +2171,17 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.5.0: +buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2091,7 +2278,7 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^5.3.0: +chalk@^5.0.1, chalk@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== @@ -2101,6 +2288,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +character-entities@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -2121,11 +2313,23 @@ chokidar@3.6.0, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== +chromium-bidi@0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.7.tgz#4c022c2b0fb1d1c9b571fadf373042160e71d236" + integrity sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ== + dependencies: + mitt "3.0.0" + ci-info@^3.2.0: version "3.9.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" @@ -2248,15 +2452,25 @@ commander@4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@7, commander@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== comment-json@4.2.3: version "4.2.3" @@ -2349,6 +2563,23 @@ cors@2.8.5: object-assign "^4" vary "^1" +cose-base@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-1.0.3.tgz#650334b41b869578a543358b80cda7e0abe0a60a" + integrity sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg== + dependencies: + layout-base "^1.0.0" + +cosmiconfig@8.1.3: + version "8.1.3" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.1.3.tgz#0e614a118fcc2d9e5afc2f87d53cd09931015689" + integrity sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw== + dependencies: + import-fresh "^3.2.1" + js-yaml "^4.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + cosmiconfig@^8.2.0: version "8.3.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" @@ -2377,6 +2608,13 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -2395,6 +2633,297 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +cytoscape-cose-bilkent@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz#762fa121df9930ffeb51a495d87917c570ac209b" + integrity sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ== + dependencies: + cose-base "^1.0.0" + +cytoscape@^3.28.1: + version "3.30.1" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.30.1.tgz#9855a284aaefbaf2628fdc6cf956ba83c0ae511b" + integrity sha512-TRJc3HbBPkHd50u9YfJh2FxD1lDLZ+JXnJoyBn5LkncoeuT7fapO/Hq/Ed8TdFclaKshzInge2i30bg7VKeoPQ== + +"d3-array@1 - 2": + version "2.12.1" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" + integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ== + dependencies: + internmap "^1.0.0" + +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + +d3-axis@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + +d3-brush@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-contour@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc" + integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA== + dependencies: + d3-array "^3.2.0" + +d3-delaunay@6: + version "6.0.4" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" + integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +d3-fetch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + +d3-force@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +d3-geo@3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d" + integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" + integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +d3-path@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + +d3-random@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +d3-sankey@^0.12.3: + version "0.12.3" + resolved "https://registry.yarnpkg.com/d3-sankey/-/d3-sankey-0.12.3.tgz#b3c268627bd72e5d80336e8de6acbfec9d15d01d" + integrity sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ== + dependencies: + d3-array "1 - 2" + d3-shape "^1.2.0" + +d3-scale-chromatic@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +d3-scale@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +d3-shape@3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +d3-shape@^1.2.0: + version "1.3.7" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" + +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.4.0, d3@^7.8.2: + version "7.9.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.9.0.tgz#579e7acb3d749caf8860bd1741ae8d371070cd5d" + integrity sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "4" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + +dagre-d3-es@7.0.10: + version "7.0.10" + resolved "https://registry.yarnpkg.com/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz#19800d4be674379a3cd8c86a8216a2ac6827cadc" + integrity sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A== + dependencies: + d3 "^7.8.2" + lodash-es "^4.17.21" + data-view-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" @@ -2422,6 +2951,11 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" +dayjs@^1.11.7: + version "1.11.12" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.12.tgz#5245226cc7f40a15bf52e0b99fd2a04669ccac1d" + integrity sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2429,6 +2963,20 @@ debug@2.6.9: dependencies: ms "2.0.0" +debug@4, debug@^4.0.0: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -2436,12 +2984,12 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +decode-named-character-reference@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" + integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== dependencies: - ms "2.1.2" + character-entities "^2.0.0" decompress-response@^6.0.0: version "6.0.0" @@ -2495,6 +3043,13 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delaunator@5: + version "5.0.1" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" + integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw== + dependencies: + robust-predicates "^3.0.2" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -2505,6 +3060,11 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -2515,6 +3075,11 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +devtools-protocol@0.0.1107588: + version "0.0.1107588" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1107588.tgz#f8cac707840b97cc30b029359341bcbbb0ad8ffa" + integrity sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg== + dezalgo@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" @@ -2533,6 +3098,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -2559,12 +3129,17 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dompurify@^3.0.5: + version "3.1.6" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2" + integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ== + dotenv-expand@10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== -dotenv@16.4.5: +dotenv@16.4.5, dotenv@^16.3.1: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== @@ -2584,6 +3159,11 @@ electron-to-chromium@^1.4.668: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.734.tgz#6e0083e1a6be06b2df4c849ba1534d86f30a6738" integrity sha512-pYfGUc+ll8AOzLbLC0lfgwkvCZIV+sKGuFFsSNuF3K3ujrmem8jIjg/t6DNq0J7biTSS1hCt/Hts0nmA3ZyprQ== +elkjs@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.9.3.tgz#16711f8ceb09f1b12b99e971b138a8384a529161" + integrity sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ== + emittery@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" @@ -2604,7 +3184,7 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.1.0: +end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -2827,9 +3407,9 @@ eslint-plugin-prettier@^5.1.3: synckit "^0.8.6" eslint-plugin-simple-import-sort@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.0.0.tgz#3cfa05d74509bd4dc329a956938823812194dbb6" - integrity sha512-8o0dVEdAkYap0Cn5kNeklaKcT1nUsa3LITWEuFk3nJifOoD+5JQGoyDUW2W/iPWwBsNBJpyJS9y4je/BgxLcyQ== + version "12.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.0.tgz#8186ad55474d2f5c986a2f1bf70625a981e30d05" + integrity sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig== eslint-scope@5.1.1: version "5.1.1" @@ -3061,6 +3641,17 @@ external-editor@^3.0.3, external-editor@^3.1.0: iconv-lite "^0.4.24" tmp "^0.0.33" +extract-zip@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3111,6 +3702,13 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== + dependencies: + pend "~1.2.0" + figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -3280,6 +3878,11 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" @@ -3585,6 +4188,14 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +https-proxy-agent@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -3597,6 +4208,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@0.6: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -3697,6 +4315,16 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + +internmap@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" + integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== + interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" @@ -4415,6 +5043,13 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +katex@^0.16.9: + version "0.16.11" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.11.tgz#4bc84d5584f996abece5f01c6ad11304276a33f5" + integrity sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ== + dependencies: + commander "^8.3.0" + keyv@^4.0.0, keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -4422,11 +5057,26 @@ keyv@^4.0.0, keyv@^4.5.3: dependencies: json-buffer "3.0.1" +khroma@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" + integrity sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw== + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +kleur@^4.0.3: + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + +layout-base@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-1.0.2.tgz#1291e296883c322a9dd4c5dd82063721b53e26e2" + integrity sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg== + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -4469,6 +5119,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -4563,6 +5218,31 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +mdast-util-from-markdown@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" + integrity sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + decode-named-character-reference "^1.0.0" + mdast-util-to-string "^3.1.0" + micromark "^3.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-decode-string "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-stringify-position "^3.0.0" + uvu "^0.5.0" + +mdast-util-to-string@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz#66f7bb6324756741c5f47a53557f0cbf16b6f789" + integrity sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg== + dependencies: + "@types/mdast" "^3.0.0" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -4590,11 +5270,231 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +mermaid@^10.8.0: + version "10.9.1" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-10.9.1.tgz#5f582c23f3186c46c6aa673e59eeb46d741b2ea6" + integrity sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA== + dependencies: + "@braintree/sanitize-url" "^6.0.1" + "@types/d3-scale" "^4.0.3" + "@types/d3-scale-chromatic" "^3.0.0" + cytoscape "^3.28.1" + cytoscape-cose-bilkent "^4.1.0" + d3 "^7.4.0" + d3-sankey "^0.12.3" + dagre-d3-es "7.0.10" + dayjs "^1.11.7" + dompurify "^3.0.5" + elkjs "^0.9.0" + katex "^0.16.9" + khroma "^2.0.0" + lodash-es "^4.17.21" + mdast-util-from-markdown "^1.3.0" + non-layered-tidy-tree-layout "^2.0.2" + stylis "^4.1.3" + ts-dedent "^2.2.0" + uuid "^9.0.0" + web-worker "^1.2.0" + methods@^1.1.2, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micromark-core-commonmark@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz#1386628df59946b2d39fb2edfd10f3e8e0a75bb8" + integrity sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-factory-destination "^1.0.0" + micromark-factory-label "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-factory-title "^1.0.0" + micromark-factory-whitespace "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-html-tag-name "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + +micromark-factory-destination@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz#eb815957d83e6d44479b3df640f010edad667b9f" + integrity sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-label@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz#cc95d5478269085cfa2a7282b3de26eb2e2dec68" + integrity sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-factory-space@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz#c8f40b0640a0150751d3345ed885a080b0d15faf" + integrity sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-title@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz#dd0fe951d7a0ac71bdc5ee13e5d1465ad7f50ea1" + integrity sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-whitespace@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz#798fb7489f4c8abafa7ca77eed6b5745853c9705" + integrity sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-character@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz#4fedaa3646db249bc58caeb000eb3549a8ca5dcc" + integrity sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-chunked@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz#37a24d33333c8c69a74ba12a14651fd9ea8a368b" + integrity sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-classify-character@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz#6a7f8c8838e8a120c8e3c4f2ae97a2bff9190e9d" + integrity sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-combine-extensions@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz#192e2b3d6567660a85f735e54d8ea6e3952dbe84" + integrity sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-decode-numeric-character-reference@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz#b1e6e17009b1f20bc652a521309c5f22c85eb1c6" + integrity sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-decode-string@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz#dc12b078cba7a3ff690d0203f95b5d5537f2809c" + integrity sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz#92e4f565fd4ccb19e0dcae1afab9a173bbeb19a5" + integrity sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw== + +micromark-util-html-tag-name@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz#48fd7a25826f29d2f71479d3b4e83e94829b3588" + integrity sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q== + +micromark-util-normalize-identifier@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz#7a73f824eb9f10d442b4d7f120fecb9b38ebf8b7" + integrity sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-resolve-all@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz#4652a591ee8c8fa06714c9b54cd6c8e693671188" + integrity sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA== + dependencies: + micromark-util-types "^1.0.0" + +micromark-util-sanitize-uri@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz#613f738e4400c6eedbc53590c67b197e30d7f90d" + integrity sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-subtokenize@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz#941c74f93a93eaf687b9054aeb94642b0e92edb1" + integrity sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-util-symbol@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz#813cd17837bdb912d069a12ebe3a44b6f7063142" + integrity sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag== + +micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz#e6676a8cae0bb86a2171c498167971886cb7e283" + integrity sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg== + +micromark@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.2.0.tgz#1af9fef3f995ea1ea4ac9c7e2f19c48fd5c006e9" + integrity sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA== + dependencies: + "@types/debug" "^4.0.0" + debug "^4.0.0" + decode-named-character-reference "^1.0.0" + micromark-core-commonmark "^1.0.1" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + micromatch@^4.0.0, micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -4683,6 +5583,16 @@ minipass@^4.2.4: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== +mitt@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd" + integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ== + +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp@^0.5.4: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -4690,6 +5600,11 @@ mkdirp@^0.5.4: dependencies: minimist "^1.2.6" +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -4755,6 +5670,13 @@ node-emoji@1.11.0: dependencies: lodash "^4.17.21" +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^2.6.1: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -4772,6 +5694,11 @@ node-releases@^2.0.14: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +non-layered-tidy-tree-layout@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz#57d35d13c356643fc296a55fb11ac15e74da7804" + integrity sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw== + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -4968,7 +5895,7 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^5.2.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -5043,6 +5970,11 @@ peek-readable@^5.0.0: resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0.tgz#7ead2aff25dc40458c60347ea76cfdfd63efdfec" integrity sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A== +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -5129,18 +6061,32 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" +prisma-erd-generator@^1.11.2: + version "1.11.2" + resolved "https://registry.yarnpkg.com/prisma-erd-generator/-/prisma-erd-generator-1.11.2.tgz#75b4321f212d0837e75f98230b03abc3488ff71f" + integrity sha512-abo2EBIjqJALfjm8p+uOsQk38DlU3rlLJA9/cOvcLLt8A9bjMkRwlqaZDAD/iXVZcXJRJPgJ98fEviTa+w8oTQ== + dependencies: + "@mermaid-js/mermaid-cli" "^10.6.1" + "@prisma/generator-helper" "^4.0.0 || ^5.0.0" + dotenv "^16.3.1" + prisma@^5.7.1: - version "5.12.1" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.12.1.tgz#db4596253bb066afc9f08744642f200a398d8d51" - integrity sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q== + version "5.15.0" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.15.0.tgz#887c295caa1b81b8849d94a2751cc0e0994f86d1" + integrity sha512-JA81ACQSCi3a7NUOgonOIkdx8PAVkO+HbUOxmd00Yb8DgIIEpr2V9+Qe/j6MLxIgWtE/OtVQ54rVjfYRbZsCfw== dependencies: - "@prisma/engines" "5.12.1" + "@prisma/engines" "5.15.0" process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +progress@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -5157,7 +6103,7 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-from-env@^1.1.0: +proxy-from-env@1.1.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== @@ -5180,6 +6126,35 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +puppeteer-core@19.11.1: + version "19.11.1" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-19.11.1.tgz#4c63d7a0a6cd268ff054ebcac315b646eee32667" + integrity sha512-qcuC2Uf0Fwdj9wNtaTZ2OvYRraXpAK+puwwVW8ofOhOgLPZyz1c68tsorfIZyCUOpyBisjr+xByu7BMbEYMepA== + dependencies: + "@puppeteer/browsers" "0.5.0" + chromium-bidi "0.4.7" + cross-fetch "3.1.5" + debug "4.3.4" + devtools-protocol "0.0.1107588" + extract-zip "2.0.1" + https-proxy-agent "5.0.1" + proxy-from-env "1.1.0" + tar-fs "2.1.1" + unbzip2-stream "1.4.3" + ws "8.13.0" + +puppeteer@^19.0.0: + version "19.11.1" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-19.11.1.tgz#bb75d518e87b0b4f6ef9bad1ea7e9d1cdcd18a5d" + integrity sha512-39olGaX2djYUdhaQQHDZ0T0GwEp+5f9UB9HmEP0qHfdQHIq0xGQZuAZ5TLnJIc/88SrPLpEflPC+xUqOTv3c5g== + dependencies: + "@puppeteer/browsers" "0.5.0" + cosmiconfig "8.1.3" + https-proxy-agent "5.0.1" + progress "2.0.3" + proxy-from-env "1.1.0" + puppeteer-core "19.11.1" + pure-rand@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" @@ -5249,7 +6224,7 @@ readable-stream@^2.2.2: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -5384,6 +6359,11 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +robust-predicates@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== + run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -5401,6 +6381,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + rxjs@7.8.1, rxjs@^7.5.5, rxjs@^7.8.1: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" @@ -5408,6 +6393,13 @@ rxjs@7.8.1, rxjs@^7.5.5, rxjs@^7.8.1: dependencies: tslib "^2.1.0" +sade@^1.7.3: + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + safe-array-concat@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" @@ -5437,7 +6429,7 @@ safe-regex-test@^1.0.3: es-errors "^1.3.0" is-regex "^1.1.4" -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -5790,6 +6782,11 @@ strtok3@^7.0.0-alpha.9: "@tokenizer/token" "^0.3.0" peek-readable "^5.0.0" +stylis@^4.1.3: + version "4.3.2" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444" + integrity sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg== + superagent@^8.1.2: version "8.1.2" resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.1.2.tgz#03cb7da3ec8b32472c9d20f6c2a57c7f3765f30b" @@ -5863,6 +6860,27 @@ tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar-fs@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + 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" + terser-webpack-plugin@^5.3.10: version "5.3.10" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" @@ -5898,7 +6916,7 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -through@^2.3.6: +through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -5962,6 +6980,11 @@ ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + ts-jest@^29.1.0: version "29.1.2" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" @@ -6154,11 +7177,26 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +unbzip2-stream@1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + undici-types@~5.26.4: version "5.26.5" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +unist-util-stringify-position@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz#03ad3348210c2d930772d64b489580c13a7db39d" + integrity sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg== + dependencies: + "@types/unist" "^2.0.0" + universalify@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" @@ -6194,11 +7232,21 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@9.0.1, uuid@^9.0.1: +uuid@9.0.1, uuid@^9.0.0, uuid@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== +uvu@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" + integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== + dependencies: + dequal "^2.0.0" + diff "^5.0.0" + kleur "^4.0.3" + sade "^1.7.3" + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" @@ -6258,6 +7306,11 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +web-worker@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.3.0.tgz#e5f2df5c7fe356755a5fb8f8410d4312627e6776" + integrity sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -6388,6 +7441,11 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -6418,6 +7476,19 @@ yargs-parser@21.1.1, yargs-parser@^21.0.1, yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs@17.7.1: + version "17.7.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" + integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== + 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" + yargs@^17.3.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" @@ -6431,6 +7502,14 @@ yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"